/** * Game Loop Module for AI Interactive Fiction * Manages the main game logic and connects various modules */ import { BaseModule } from './base-module.js'; import { moduleRegistry } from './module-registry.js'; class GameLoopModule extends BaseModule { constructor() { super('game-loop', 'Game Loop'); this.uiController = null; this.socketClient = null; this.ttsPlayer = null; this.textBuffer = null; this.isRunning = false; this.gameState = { started: false, canLoad: false, currentRoom: null, inventory: [], commandHistory: [] }; } /** * Load module dependencies * @returns {Promise} - Resolves when dependencies are loaded */ async loadDependencies() { // Basic dependency declaration - details handled in waitForDependencies return true; } /** * Wait for dependencies to be ready */ async waitForDependencies() { try { // Wait for TTS module with a timeout const ttsReady = await moduleRegistry.waitForModule('tts', 15000); if (ttsReady) { this.ttsPlayer = moduleRegistry.getModule('tts'); this.reportProgress(30, "TTS module ready"); } else { console.warn("TTS module not ready, game will have limited functionality"); } // Wait for UI Controller with a timeout const uiReady = await moduleRegistry.waitForModule('ui-controller', 15000); if (uiReady) { this.uiController = moduleRegistry.getModule('ui-controller'); this.reportProgress(50, "UI Controller ready"); } else { console.warn("UI Controller not ready, game will have limited functionality"); } // Get text buffer reference this.textBuffer = moduleRegistry.getModule('text-buffer'); if (this.textBuffer) { this.reportProgress(60, "Text buffer ready"); } // Continue even with limited functionality return true; } catch (error) { console.error("Error waiting for dependencies:", error); return false; } } /** * Initialize the module * @returns {Promise} - Resolves with success status */ async initialize() { this.reportProgress(100, "Game loop initialized"); return true; } /** * Start the game loop */ start() { console.log("GameLoop: Starting game sequence..."); try { // Update UI with initial game state if (this.uiController && this.ttsPlayer) { this.updateUIState(); } else { console.warn("GameLoop: UI Controller or TTS Player not ready for status update."); } console.log("GameLoop: Setting up socket listeners and connecting..."); // Set up socket event listeners and connect this.setupSocketEventListeners(); // Set the game loop as running this.isRunning = true; } catch (error) { console.error("Error starting game loop:", error); } } /** * Set up socket event listeners and connect to server */ setupSocketEventListeners() { // Get the socket client module this.socketClient = moduleRegistry.getModule('socket-client'); if (!this.socketClient) { console.error("Socket client module not found"); return; } // Connect UI controller to socket client for command handling if (this.uiController) { this.uiController.socketClient = this.socketClient; } else { console.warn("GameLoop: UI Controller not ready for Socket Client assignment."); } // Listen for socket connection event this.socketClient.on('connect', () => { console.log("GameLoop: Socket connected event received."); // Request a new game start when we (re)connect console.log("GameLoop: Requesting start game on (re)connect."); this.requestStartGame(); }); // Listen for game state updates this.socketClient.on('gameStateUpdate', (data) => { console.log("GameLoop: Game state update received", data); this.updateGameState(data); }); // Listen for narrative responses this.socketClient.on('narrativeResponse', (data) => { console.log("GameLoop: Narrative response received", data); // Text processing is handled by socket-client -> text-buffer -> ui-controller pipeline }); // Listen for game introduction this.socketClient.on('gameIntroduction', (data) => { console.log("GameLoop: Received gameIntroduction"); this.gameState.started = true; this.updateUIState(); // Text processing is handled by socket-client -> text-buffer -> ui-controller pipeline }); // Connect to the socket server this.socketClient.connect().then(success => { if (success) { console.log("GameLoop: Socket connection established successfully."); console.log("GameLoop: Requesting to start a new game"); this.requestStartGame(); } else { console.error("GameLoop: Failed to connect to socket server"); } }); } /** * Update the game state * @param {Object} data - New game state data */ updateGameState(data) { if (!data) return; // Update game state if (data.currentRoom) { this.gameState.currentRoom = data.currentRoom; } if (data.inventory) { this.gameState.inventory = data.inventory; } // Update UI with new game state this.updateUIState(); } /** * Update UI with current game state */ updateUIState() { if (!this.uiController) return; // Update UI components based on game state this.uiController.updateButtonStates(this.gameState); } /** * Request to start a new game */ requestStartGame() { if (!this.socketClient) return; this.socketClient.requestStartGame(); this.gameState.started = true; } /** * Request to save the current game */ requestSaveGame() { if (!this.socketClient) return; this.socketClient.requestSaveGame(); } /** * Request to load a saved game */ requestLoadGame() { if (!this.socketClient) return; this.socketClient.requestLoadGame(); } /** * Manually add text to the buffer * Useful for testing or adding local messages * @param {string} text - Text to add */ addText(text) { if (!this.textBuffer) { console.warn("Text buffer not available"); return; } this.textBuffer.addText(text); } } // Create the singleton instance const GameLoop = new GameLoopModule(); // Register with the module registry moduleRegistry.register(GameLoop); // Export the module export { GameLoop }; // Keep a reference in window for loader system window.GameLoop = GameLoop;