Files
ai.interactive.fiction/public/js/socket-client.js
T

177 lines
4.8 KiB
JavaScript

/**
* Socket Client Module
* Manages WebSocket communication with the game server.
*/
export class SocketClient {
constructor(serverUrl) {
this.socket = null;
this.serverUrl = serverUrl || window.location.origin; // Default to current origin
this.eventListeners = {
connect: [],
disconnect: [],
connect_error: [],
gameIntroduction: [],
narrativeResponse: [],
gameSaved: [],
gameLoaded: [],
error: [],
};
}
/**
* Connects to the WebSocket server.
*/
connect() {
if (this.socket && this.socket.connected) {
console.log('SocketClient: Already connected.');
return;
}
console.log(`SocketClient: Connecting to ${this.serverUrl}...`);
// Ensure io is available (it should be loaded globally)
if (typeof io === 'undefined') {
console.error('Socket.IO client library (io) not found. Make sure it is loaded.');
this.triggerEvent('error', { message: 'Socket.IO library not loaded.' });
return;
}
this.socket = io(this.serverUrl, {
reconnectionAttempts: 5,
timeout: 10000,
});
this.initializeSocketEventHandlers();
}
/**
* Disconnects from the server.
*/
disconnect() {
if (this.socket) {
console.log('SocketClient: Disconnecting...');
this.socket.disconnect();
}
}
/**
* Checks if the client is currently connected.
* @returns {boolean} True if connected, false otherwise.
*/
isConnected() {
return this.socket && this.socket.connected;
}
/**
* Sets up the listeners for standard socket events.
*/
initializeSocketEventHandlers() {
if (!this.socket) return;
this.socket.on('connect', () => {
console.log('SocketClient: Connected to server.');
this.triggerEvent('connect');
});
this.socket.on('disconnect', (reason) => {
console.log(`SocketClient: Disconnected from server. Reason: ${reason}`);
this.triggerEvent('disconnect', reason);
});
this.socket.on('connect_error', (error) => {
console.error('SocketClient: Connection error:', error);
this.triggerEvent('connect_error', error);
});
// --- Game-specific events ---
this.socket.on('gameIntroduction', (data) => {
console.log('SocketClient: Received gameIntroduction');
this.triggerEvent('gameIntroduction', data);
});
this.socket.on('narrativeResponse', (data) => {
console.log('SocketClient: Received narrativeResponse');
this.triggerEvent('narrativeResponse', data);
});
this.socket.on('gameSaved', (data) => {
console.log('SocketClient: Received gameSaved confirmation');
this.triggerEvent('gameSaved', data); // Pass data if any
});
this.socket.on('gameLoaded', (data) => {
console.log('SocketClient: Received gameLoaded confirmation');
this.triggerEvent('gameLoaded', data);
});
this.socket.on('error', (data) => {
console.error('SocketClient: Received error from server:', data);
this.triggerEvent('error', data);
});
}
/**
* Registers a listener for a specific event.
* @param {string} eventName - The name of the event.
* @param {function} callback - The function to call when the event occurs.
*/
on(eventName, callback) {
if (this.eventListeners[eventName]) {
this.eventListeners[eventName].push(callback);
} else {
console.warn(`SocketClient: Attempted to register listener for unknown event "${eventName}"`);
}
}
/**
* Triggers a specific event, calling all registered listeners.
* @param {string} eventName - The name of the event.
* @param {*} data - Data to pass to the listeners.
*/
triggerEvent(eventName, data) {
if (this.eventListeners[eventName]) {
this.eventListeners[eventName].forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`SocketClient: Error in event listener for "${eventName}":`, error);
}
});
}
}
/**
* Emits an event to the server.
* @param {string} eventName - The name of the event to emit.
* @param {object} data - The data to send with the event.
*/
emit(eventName, data) {
if (this.socket && this.socket.connected) {
console.log(`SocketClient: Emitting "${eventName}"`, data || '');
this.socket.emit(eventName, data);
} else {
console.error(`SocketClient: Cannot emit "${eventName}", not connected.`);
// Optionally trigger an error event or queue the message
this.triggerEvent('error', { message: `Cannot send command "${eventName}", not connected.` });
}
}
// --- Convenience methods for game actions ---
requestStartGame() {
this.emit('startGame');
}
sendCommand(command) {
this.emit('playerCommand', { command });
}
requestSaveGame() {
this.emit('saveGame');
}
requestLoadGame() {
this.emit('loadGame');
}
}