Checkpoint current interactive fiction state

This commit is contained in:
2026-05-14 21:17:43 +02:00
parent c745efd1d2
commit 873049f7e6
183 changed files with 13755 additions and 1459 deletions
+100 -20
View File
@@ -9,7 +9,7 @@ class GameLoopModule extends BaseModule {
super('game-loop', 'Game Loop');
// Dependencies
this.dependencies = ['ui-controller', 'socket-client', 'tts-player', 'text-buffer'];
this.dependencies = ['ui-controller', 'socket-client', 'text-buffer'];
// Game state
this.gameState = {
@@ -25,9 +25,11 @@ class GameLoopModule extends BaseModule {
// Bind methods using parent's bindMethods utility
this.bindMethods([
'start',
'setupUiEventListeners',
'setupSocketEventListeners',
'updateGameState',
'updateUIState',
'refreshGameApiState',
'requestStartGame',
'requestSaveGame',
'requestLoadGame',
@@ -46,6 +48,7 @@ class GameLoopModule extends BaseModule {
try {
// The dependencies are now automatically available via getModule
this.updateUIState();
this.setupUiEventListeners();
console.log("GameLoop: Setting up socket listeners and connecting...");
@@ -58,6 +61,15 @@ class GameLoopModule extends BaseModule {
console.error("Error starting game loop:", error);
}
}
setupUiEventListeners() {
if (this.uiEventsBound) return;
this.uiEventsBound = true;
document.addEventListener('ui:game:restart', () => this.requestStartGame());
document.addEventListener('ui:game:save', () => this.requestSaveGame());
document.addEventListener('ui:game:load', () => this.requestLoadGame());
}
setupSocketEventListeners() {
// Get the socket client module using parent's getModule method
@@ -81,14 +93,7 @@ class GameLoopModule extends BaseModule {
socketClient.on('connect', () => {
console.log("GameLoop: Socket connected event received.");
// Request a new game start when we connect
// Only request start game if one isn't already in progress
if (!this.gameState.started) {
console.log("GameLoop: Requesting start game on connect.");
this.requestStartGame();
} else {
console.log("GameLoop: Game already started, skipping duplicate start request.");
}
this.refreshGameApiState();
});
// Listen for game state updates
@@ -107,9 +112,22 @@ class GameLoopModule extends BaseModule {
socketClient.on('gameIntroduction', (data) => {
console.log("GameLoop: Received gameIntroduction");
this.gameState.started = true;
this.gameState.canSave = true;
this.updateUIState();
// Text processing is handled by socket-client -> text-buffer -> ui-controller pipeline
});
socketClient.on('gameSaved', () => {
this.gameState.canLoad = true;
this.updateUIState();
});
socketClient.on('gameLoaded', () => {
this.gameState.started = true;
this.gameState.canSave = true;
this.gameState.canLoad = true;
this.updateUIState();
});
// Connect to the socket server
socketClient.connect().then(success => {
@@ -120,6 +138,21 @@ class GameLoopModule extends BaseModule {
}
});
}
async refreshGameApiState() {
const socketClient = this.getModule('socket-client');
if (!socketClient || !socketClient.getConnectionStatus()) return;
const [running, hasSave] = await Promise.all([
socketClient.isGameRunning(),
socketClient.hasSaveGame(1)
]);
this.gameState.started = Boolean(running?.result);
this.gameState.canSave = this.gameState.started;
this.gameState.canLoad = Boolean(hasSave?.result);
this.updateUIState();
}
/**
* Update the game state
@@ -149,38 +182,85 @@ class GameLoopModule extends BaseModule {
if (!uiController) return;
// Update UI components based on game state
uiController.updateButtonStates(this.gameState);
const state = {
canRestart: true,
canSave: Boolean(this.gameState.started),
canLoad: Boolean(this.gameState.canLoad),
gameStarted: Boolean(this.gameState.started)
};
document.body.dataset.gameRunning = state.gameStarted ? 'true' : 'false';
uiController.updateButtonStates(state);
}
/**
* Request to start a new game
*/
requestStartGame() {
async requestStartGame() {
const socketClient = this.getModule('socket-client');
if (!socketClient) return;
socketClient.requestStartGame();
const uiController = this.getModule('ui-controller');
if (uiController) {
uiController.clearDisplay();
}
const textBuffer = this.getModule('text-buffer');
if (textBuffer && typeof textBuffer.clear === 'function') {
textBuffer.clear();
}
const response = await socketClient.newGame();
if (!response?.success) {
console.error('GameLoop: newGame failed', response);
return;
}
this.gameState.started = true;
this.gameState.canSave = true;
this.gameState.canLoad = Boolean(response.canLoad);
this.updateUIState();
}
/**
* Request to save the current game
*/
requestSaveGame() {
async requestSaveGame() {
const socketClient = this.getModule('socket-client');
if (!socketClient) return;
socketClient.requestSaveGame();
if (!socketClient || !this.gameState.started) return;
const response = await socketClient.saveGame(1);
if (response?.success) {
this.gameState.canLoad = true;
this.updateUIState();
}
}
/**
* Request to load a saved game
*/
requestLoadGame() {
async requestLoadGame() {
const socketClient = this.getModule('socket-client');
if (!socketClient) return;
socketClient.requestLoadGame();
const hasSave = await socketClient.hasSaveGame(1);
if (!hasSave?.result) {
this.gameState.canLoad = false;
this.updateUIState();
return;
}
const uiController = this.getModule('ui-controller');
if (uiController) {
uiController.clearDisplay();
}
const textBuffer = this.getModule('text-buffer');
if (textBuffer && typeof textBuffer.clear === 'function') {
textBuffer.clear();
}
const response = await socketClient.loadGame(1);
if (response?.success) {
this.gameState.started = true;
this.gameState.canSave = true;
this.gameState.canLoad = true;
this.updateUIState();
}
}
/**