Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
7.6 kB · 184 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184import { Server, Socket } from 'socket.io';import { gameStateManager } from './gameState';import { ClientToServerEvents, ServerToClientEvents, ServerToClientEventShapes, GameState, GameStateClient } from '../types';
// Helper function to convert GameState to GameStateClient (remove ID)function toGameStateClient(gameState: GameState): GameStateClient { const { id, ...gameStateClient } = gameState; return gameStateClient;}
interface ExtendedSocket extends Socket<ClientToServerEvents, ServerToClientEvents> { gameId?: string; playerId?: string;}
export function setupSocketIO(io: Server<ClientToServerEvents, ServerToClientEvents>) { io.on('connection', (socket: ExtendedSocket) => { console.log('Socket.io client connected:', socket.id); socket.on('authenticatePlayer', (data) => { const { gameId, playerId } = data; console.log(`Authenticating player ${playerId} for game ${gameId} on socket ${socket.id}`); // Register the socket with the player const registered = gameStateManager.maybeRegisterPlayerSocket(gameId, playerId, socket.id); if (registered) { // Store player info on socket for easier access socket.gameId = gameId; socket.playerId = playerId; // Join the game room socket.join(gameId); // Broadcast updated game state to all players in the room const gameState = gameStateManager.maybeGetGame(gameId); if (gameState) { broadcastToGame(gameId, 'gameState', toGameStateClient(gameState)); } console.log(`Player ${playerId} authenticated and joined room ${gameId}`); } else { console.error(`Failed to authenticate player ${playerId} for game ${gameId}`); socket.emit('error', { error: 'Authentication failed' }); } });
socket.on('updateRuleset', (data) => { const { gameId, ruleset } = data; console.log(`Updating ruleset for game ${gameId} from socket ${socket.id}`); // Verify the socket is authenticated for this game if (socket.gameId !== gameId) { console.error(`Socket ${socket.id} not authenticated for game ${gameId}`); socket.emit('error', { error: 'Not authenticated for this game' }); return; } // Update the ruleset via game state manager const updatedGameState = gameStateManager.maybeUpdateRuleset(gameId, ruleset); if (updatedGameState) { // Broadcast updated game state to all players in the room broadcastToGame(gameId, 'gameState', toGameStateClient(updatedGameState)); console.log(`Ruleset updated and broadcasted for game ${gameId}`); } else { console.error(`Failed to update ruleset for game ${gameId}`); socket.emit('error', { error: 'Failed to update ruleset' }); } });
socket.on('startGame', async (data) => { const { gameId } = data;
// Verify the socket is authenticated for this game if (socket.gameId !== gameId) { console.error(`Socket ${socket.id} not authenticated for game ${gameId}`); socket.emit('error', { error: 'Not authenticated for this game' }); return; }
console.log(`Starting game ${gameId} from socket ${socket.id}`);
// Start the game via game state manager const startedGameState = await gameStateManager.maybeStartGame(gameId); if (startedGameState) { // Broadcast updated game state to all players in the room broadcastToGame(gameId, 'gameState', toGameStateClient(startedGameState)); console.log(`Game ${gameId} started and broadcasted`); } else { console.error(`Failed to start game ${gameId}`); socket.emit('error', { error: 'Failed to start game' }); } });
socket.on('confirmRoleAssignment', async (data) => { const { gameId, playerId } = data; console.log(`Player ${playerId} confirming role assignment for game ${gameId} on socket ${socket.id}`);
// Verify the socket is authenticated for this game and player if (socket.gameId !== gameId || socket.playerId !== playerId) { console.error(`Socket ${socket.id} not authenticated for game ${gameId} and player ${playerId}`); socket.emit('error', { error: 'Not authenticated for this game/player' }); return; }
// Update the player's confirmation status via game state manager const updatedGameState = await gameStateManager.maybeConfirmPlayerRoleAssignment(gameId, playerId); if (updatedGameState) { // Broadcast updated game state to all players in the room broadcastToGame(gameId, 'gameState', toGameStateClient(updatedGameState)); console.log(`Player ${playerId} confirmed role assignment for game ${gameId}`); } else { console.error(`Failed to confirm role assignment for player ${playerId} in game ${gameId}`); //socket.emit('error', { error: 'Failed to confirm role assignment' }); } });
socket.on('endTurn', async (data) => { const { gameId, playerId } = socket; console.log(`Player ${playerId} ending turn for game ${gameId} on socket ${socket.id}`);
// Verify the socket is authenticated for this game and player if (!gameId || !playerId) { console.error(`Socket ${socket.id} not authenticated for any game/player`); socket.emit('error', { error: 'Not authenticated for any game/player' }); return; }
// Update the player's turn status via game state manager const updatedGameState = await gameStateManager.maybeEndPlayerTurn(gameId, playerId);
if (updatedGameState) { // Broadcast updated game state to all players in the room broadcastToGame(gameId, 'gameState', toGameStateClient(updatedGameState)); console.log(`Player ${playerId} ended turn for game ${gameId}`); } else { console.error(`Failed to end turn for player ${playerId} in game ${gameId}`); } });
socket.on('disconnect', () => { console.log('Socket.io client disconnected:', socket.id); // Use the socket registry to identify the disconnecting player const mapping = gameStateManager.maybeUnregisterSocket(socket.id); if (mapping) { // Leave the game room socket.leave(mapping.gameId); // Broadcast updated game state to remaining players in the room const gameState = gameStateManager.maybeGetGame(mapping.gameId); if (gameState) { broadcastToGame(mapping.gameId, 'gameState', toGameStateClient(gameState)); } console.log(`Player ${mapping.playerId} disconnected from game ${mapping.gameId}`); } });
socket.on('error', (error) => { console.error('Socket.io error:', error); }); });}
export function broadcastToGame<K extends keyof ServerToClientEventShapes>(gameId: string, event: K, data: ServerToClientEventShapes[K]) { const io = global.io as Server<ClientToServerEvents, ServerToClientEvents>; if (io) { // @ts-expect-error -- TS cannot infer that event is a valid key here io.to(gameId).emit(event, data); }}
export function broadcastToAll<K extends keyof ServerToClientEventShapes>(event: K, data: ServerToClientEventShapes[K]) { const io = global.io as Server<ClientToServerEvents, ServerToClientEvents>; if (io) { // @ts-expect-error -- TS cannot infer that event is a valid key here io.emit(event, data); }}