Fix stale restore after game restart

This commit is contained in:
2026-05-20 22:27:36 +02:00
parent 8258ea2321
commit beac5a2be3
12 changed files with 167 additions and 44 deletions
+21 -8
View File
@@ -87,7 +87,14 @@ function normalizeSaveSlot(slot: unknown): number {
return Number.isInteger(value) && value > 0 ? value : 1;
}
async function startDemoGameForSocket(socket: any): Promise<GameRunner> {
function withClientRequestId<T extends object>(turn: T, requestId?: number): T {
const id = Number(requestId || 0);
return Number.isInteger(id) && id > 0
? { ...turn, clientRequestId: id }
: turn;
}
async function startDemoGameForSocket(socket: any, requestId?: number): Promise<GameRunner> {
nextTurnIds.set(socket.id, 1);
const gameRunner = new GameRunner();
const worldFile = projectPath(process.env.DEFAULT_WORLD_FILE || engineConfig.paths.mainGameFile);
@@ -100,7 +107,7 @@ async function startDemoGameForSocket(socket: any): Promise<GameRunner> {
...textToParagraphs(gameState.world.introduction),
...textToParagraphs(gameRunner.getCurrentRoomDescription()),
];
socket.emit('narrativeResponse', {
socket.emit('narrativeResponse', withClientRequestId({
turnId: nextTurnId(socket.id),
paragraphs,
choices: [],
@@ -108,19 +115,19 @@ async function startDemoGameForSocket(socket: any): Promise<GameRunner> {
gameState: {
currentRoomId: gameState.currentRoomId,
},
});
}, requestId));
return gameRunner;
}
async function handleGameApi(socket: any, method: string, args: unknown[] = []) {
async function handleGameApi(socket: any, method: string, args: unknown[] = [], requestId?: number) {
const saveGames: Map<number, any> = socket.data.saveGames || new Map<number, any>();
socket.data.saveGames = saveGames;
switch (method) {
case 'newGame':
case 'newGame()':
await startDemoGameForSocket(socket);
await startDemoGameForSocket(socket, requestId);
return { success: true, result: true, running: true, canLoad: saveGames.size > 0 };
case 'loadGame':
@@ -129,8 +136,8 @@ async function handleGameApi(socket: any, method: string, args: unknown[] = [])
if (!saveGames.has(slot)) {
return { success: false, error: 'missing_save', result: false };
}
await startDemoGameForSocket(socket);
socket.emit('gameLoaded', { slot });
await startDemoGameForSocket(socket, requestId);
socket.emit('gameLoaded', { slot, clientRequestId: requestId });
return { success: true, result: true, running: true, slot };
}
@@ -174,7 +181,13 @@ io.on('connection', (socket) => {
socket.on('gameApi', async (request, respond) => {
try {
const response = await handleGameApi(socket, String(request?.method || ''), Array.isArray(request?.args) ? request.args : []);
const requestId = Number(request?.requestId || 0);
const response = await handleGameApi(
socket,
String(request?.method || ''),
Array.isArray(request?.args) ? request.args : [],
Number.isInteger(requestId) && requestId > 0 ? requestId : undefined,
);
if (typeof respond === 'function') {
respond(response);
}