252 lines
7.6 KiB
JavaScript
252 lines
7.6 KiB
JavaScript
/**
|
|
* 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<boolean>} - 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;
|