The host clears seats and closes rooms
Two lobby-lifecycle gaps from tonight's duels (a token lost to a client bug left an unkickable ghost seat holding a chair in VQJW). kickSeat: the host removes any other seat from an unstarted room — the kick is a ledger line so restarts replay it, and a kicked live socket is set adrift with notice. abandonRoom: the host dissolves a lobby or a finished game; every member is notified and detached, and the ledger is archived to rooms-abandoned/ — moved, never deleted. The lobby shows hosts a ✕ per seat and an abandon-room control. Proven live: kick with notice, kick surviving a server restart, and abandonment archiving its ledger. 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
4c7633097b
commit
9af7bd80ce
@@ -3,7 +3,7 @@
|
||||
// command. Because the engine is deterministic, replaying a file rebuilds
|
||||
// the exact game state — server restarts lose nothing.
|
||||
|
||||
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
export interface RoomMetaLine {
|
||||
@@ -58,7 +58,19 @@ export interface ChatLine {
|
||||
at: string;
|
||||
}
|
||||
|
||||
export type RoomLine = RoomMetaLine | JoinLine | StartLine | CommandLine | ChatLine;
|
||||
export interface KickLine {
|
||||
kind: "kick";
|
||||
/** The seat the host removed from an unstarted room. */
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AbandonLine {
|
||||
kind: "abandon";
|
||||
by: string;
|
||||
at: string;
|
||||
}
|
||||
|
||||
export type RoomLine = RoomMetaLine | JoinLine | StartLine | CommandLine | ChatLine | KickLine | AbandonLine;
|
||||
|
||||
const DATA_DIR = process.env.WIZWAR_DATA_DIR ?? join(process.cwd(), "data", "rooms");
|
||||
|
||||
@@ -103,3 +115,13 @@ export function readAllRooms(): Map<string, RoomLine[]> {
|
||||
}
|
||||
return rooms;
|
||||
}
|
||||
|
||||
/** Retire an abandoned room's ledger to the graveyard — never deleted,
|
||||
* only moved out of the living rooms directory. */
|
||||
export function archiveRoomFile(roomId: string): void {
|
||||
const src = join(DATA_DIR, `${roomId}.jsonl`);
|
||||
if (!existsSync(src)) return;
|
||||
const graveyard = join(DATA_DIR, "..", "rooms-abandoned");
|
||||
mkdirSync(graveyard, { recursive: true });
|
||||
renameSync(src, join(graveyard, `${roomId}.${Date.now()}.jsonl`));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user