Forced drops bank honestly; half-dead sockets confess
DROP OBJECT's forced drop hardcoded onHomeOf null and skipped the victory check — a treasure shaken loose over a home square neither reported the banking nor triggered scoring or the captured-treasures clause until something else prodded the engine. It now lands like any drop: homeOwnerAt reported, checkVictory immediate. And the stuck-game mystery from 38YP: a deploy restart left the browser holding a half-dead socket that never fired onclose, so the existing reconnect loop and masthead banner never engaged and a live game wore a frozen face. The client now pings every 15s and force- closes a socket silent for 45s, which wakes the reconnect machinery; the server answers pong. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
5eb5312637
commit
ca0a4ef2e3
@@ -277,6 +277,11 @@ function saveSeats(seats: Seat[]): void {
|
||||
|
||||
class Net {
|
||||
status = $state<"disconnected" | "connected">("disconnected");
|
||||
/** When the socket last spoke. A server restart can leave a half-dead
|
||||
* socket that never fires onclose; the watchdog closes it by hand so
|
||||
* the reconnect loop (and the masthead banner) actually engage. */
|
||||
private lastHeard = Date.now();
|
||||
private watchdog: ReturnType<typeof setInterval> | null = null;
|
||||
roomId = $state<string | null>(null);
|
||||
players = $state<string[]>([]);
|
||||
hostId = $state<string | null>(null);
|
||||
@@ -339,6 +344,14 @@ class Net {
|
||||
if (this.ws) return;
|
||||
const ws = new WebSocket(SERVER_URL);
|
||||
this.ws = ws;
|
||||
this.lastHeard = Date.now();
|
||||
if (!this.watchdog) {
|
||||
this.watchdog = setInterval(() => {
|
||||
if (!this.ws || this.status !== "connected") return;
|
||||
this.send({ type: "ping" });
|
||||
if (Date.now() - this.lastHeard > 45_000) this.ws.close();
|
||||
}, 15_000);
|
||||
}
|
||||
ws.onopen = () => {
|
||||
this.watching = null; // the first state after (re)connecting may carry a gap
|
||||
this.status = "connected";
|
||||
@@ -367,7 +380,10 @@ class Net {
|
||||
};
|
||||
ws.onmessage = (raw) => {
|
||||
const msg = JSON.parse(raw.data as string);
|
||||
this.lastHeard = Date.now();
|
||||
switch (msg.type) {
|
||||
case "pong":
|
||||
break;
|
||||
case "seat": {
|
||||
this.token = msg.token;
|
||||
const seatRoom = (this.roomIdPending ?? this.roomId ?? "").toUpperCase();
|
||||
|
||||
Reference in New Issue
Block a user