final changes
This commit is contained in:
@@ -13,8 +13,11 @@ import {
|
||||
GameActionData,
|
||||
PlayerPosition,
|
||||
GameStateUpdateData,
|
||||
FieldEffectRequest
|
||||
FieldEffectRequest,
|
||||
JoinGameData,
|
||||
LeaveGameData
|
||||
} from './Interfaces/GameInterfaces';
|
||||
import { json } from 'stream/consumers';
|
||||
|
||||
interface AuthenticatedSocket extends Socket {
|
||||
userId?: string;
|
||||
@@ -23,14 +26,6 @@ interface AuthenticatedSocket extends Socket {
|
||||
isAuthenticated?: boolean;
|
||||
}
|
||||
|
||||
interface JoinGameData {
|
||||
gameToken: string; // Required game session token
|
||||
}
|
||||
|
||||
interface LeaveGameData {
|
||||
gameCode: string;
|
||||
}
|
||||
|
||||
interface DiceRollData {
|
||||
gameCode: string;
|
||||
diceValue: number; // Value from frontend (1-6)
|
||||
@@ -91,7 +86,7 @@ export class GameWebSocketService {
|
||||
|
||||
private setupGameEventHandlers(socket: AuthenticatedSocket): void {
|
||||
// Join game room
|
||||
socket.on('game:join', async (data: JoinGameData) => {
|
||||
socket.on('game:join', async (data: any) => {
|
||||
await this.handleJoinGame(socket, data);
|
||||
});
|
||||
|
||||
@@ -141,11 +136,14 @@ export class GameWebSocketService {
|
||||
});
|
||||
}
|
||||
|
||||
private async handleJoinGame(socket: AuthenticatedSocket, data: JoinGameData): Promise<void> {
|
||||
private async handleJoinGame(socket: AuthenticatedSocket, data: any): Promise<void> {
|
||||
try {
|
||||
const { gameToken } = data;
|
||||
// Simple data extraction - let Socket.IO handle the parsing
|
||||
const jsdata = JSON.parse(data);
|
||||
const gameToken = jsdata?.gameToken;
|
||||
|
||||
if (!gameToken) {
|
||||
logError('Game join failed: No game token provided');
|
||||
socket.emit('game:error', { message: 'Game token is required' });
|
||||
return;
|
||||
}
|
||||
@@ -153,6 +151,7 @@ export class GameWebSocketService {
|
||||
// Verify the game token
|
||||
const gameTokenPayload = this.gameTokenService.verifyGameToken(gameToken);
|
||||
if (!gameTokenPayload) {
|
||||
logError('Game join failed: Invalid game token');
|
||||
socket.emit('game:error', { message: 'Invalid or expired game token' });
|
||||
return;
|
||||
}
|
||||
@@ -162,10 +161,19 @@ export class GameWebSocketService {
|
||||
// Validate game still exists
|
||||
const game = await this.gameRepository.findByGameCode(gameCode);
|
||||
if (!game || game.id !== gameId) {
|
||||
logError(`Game join failed: Game not found - Code: ${gameCode}`);
|
||||
socket.emit('game:error', { message: 'Game not found or token invalid' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if player name is already in use by checking connected players
|
||||
const connectedPlayers = await this.getConnectedPlayers(gameCode);
|
||||
if (connectedPlayers.includes(playerName)) {
|
||||
logOther(`Game join failed: Player name "${playerName}" already in use in game ${gameCode}`);
|
||||
socket.emit('game:error', { message: `Player name "${playerName}" is already in use in this game` });
|
||||
return;
|
||||
}
|
||||
|
||||
// Set socket properties from game token
|
||||
socket.gameCode = gameCode;
|
||||
socket.playerName = playerName;
|
||||
@@ -185,8 +193,6 @@ export class GameWebSocketService {
|
||||
// Add to pending players list and notify gamemaster
|
||||
await this.addToPendingPlayers(gameCode, playerName);
|
||||
|
||||
logOther(`Player ${playerName} requesting approval to join private game: ${gameRoomName}`);
|
||||
|
||||
// Send pending status to the requesting player
|
||||
socket.emit('game:pending-approval', {
|
||||
gameCode,
|
||||
@@ -210,7 +216,6 @@ export class GameWebSocketService {
|
||||
await socket.join(gameRoomName);
|
||||
await socket.join(playerRoomName);
|
||||
|
||||
logOther(`Player ${playerName} joined game room: ${gameRoomName} (${isAuthenticated ? 'authenticated' : 'public'}) ${isGamemaster ? '[GAMEMASTER]' : ''}`);
|
||||
|
||||
// Send success response to the joining player
|
||||
socket.emit('game:joined', {
|
||||
@@ -222,6 +227,7 @@ export class GameWebSocketService {
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
|
||||
// Notify other players in the game (broadcast)
|
||||
socket.to(gameRoomName).emit('game:player-joined', {
|
||||
playerName: playerName,
|
||||
@@ -230,40 +236,54 @@ export class GameWebSocketService {
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
|
||||
// Send current game state to the joining player
|
||||
const gameState = await this.getGameState(gameCode);
|
||||
socket.emit('game:state', gameState);
|
||||
|
||||
|
||||
// Update Redis with active player connection
|
||||
await this.updatePlayerConnection(gameCode, playerName, true);
|
||||
|
||||
} catch (error) {
|
||||
logError('Error joining game', error as Error);
|
||||
socket.emit('game:error', { message: 'Failed to join game' });
|
||||
socket.emit('game:error', {
|
||||
message: 'Failed to join game',
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async handleLeaveGame(socket: AuthenticatedSocket, data: LeaveGameData): Promise<void> {
|
||||
try {
|
||||
const { gameCode } = data;
|
||||
const { gameCode } = JSON.parse(data as any);
|
||||
const playerName = socket.playerName;
|
||||
|
||||
// Validate we have the required data
|
||||
if (!playerName) {
|
||||
logError('Cannot leave game: socket has no playerName');
|
||||
socket.emit('game:error', { message: 'Player has no name' });
|
||||
return;
|
||||
}
|
||||
|
||||
const gameRoomName = `game_${gameCode}`;
|
||||
const playerRoomName = `game_${gameCode}:${socket.playerName}`;
|
||||
const playerRoomName = `game_${gameCode}:${playerName}`;
|
||||
|
||||
// Leave both rooms
|
||||
await socket.leave(gameRoomName);
|
||||
await socket.leave(playerRoomName);
|
||||
|
||||
logOther(`Player ${socket.playerName} left game room: ${gameRoomName}`);
|
||||
logOther(`Player ${playerName} left game room: ${gameRoomName}`);
|
||||
|
||||
// Notify other players
|
||||
socket.to(gameRoomName).emit('game:player-left', {
|
||||
playerName: socket.playerName,
|
||||
playerName: playerName,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Update Redis
|
||||
await this.updatePlayerConnection(gameCode, socket.playerName!, false);
|
||||
// Update Redis before clearing socket properties
|
||||
await this.updatePlayerConnection(gameCode, playerName, false);
|
||||
|
||||
// Clear socket properties
|
||||
socket.gameCode = undefined;
|
||||
socket.playerName = undefined;
|
||||
|
||||
@@ -275,7 +295,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleGameAction(socket: AuthenticatedSocket, data: GameActionData): Promise<void> {
|
||||
try {
|
||||
const { gameCode, action, data: actionData } = data;
|
||||
const { gameCode, action, data: actionData } = JSON.parse(data as any);
|
||||
|
||||
if (!socket.gameCode || socket.gameCode !== gameCode) {
|
||||
socket.emit('game:error', { message: 'You must be in the game to perform actions' });
|
||||
@@ -317,7 +337,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleGameChat(socket: AuthenticatedSocket, data: GameChatData): Promise<void> {
|
||||
try {
|
||||
const { gameCode, message } = data;
|
||||
const { gameCode, message } = JSON.parse(data as any);
|
||||
|
||||
if (!socket.gameCode || socket.gameCode !== gameCode) {
|
||||
socket.emit('game:error', { message: 'You must be in the game to chat' });
|
||||
@@ -343,7 +363,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handlePlayerReady(socket: AuthenticatedSocket, data: { gameCode: string; ready: boolean }): Promise<void> {
|
||||
try {
|
||||
const { gameCode, ready } = data;
|
||||
const { gameCode, ready } = JSON.parse(data as any);
|
||||
const gameRoomName = `game_${gameCode}`;
|
||||
|
||||
// Update player ready status in Redis
|
||||
@@ -373,7 +393,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleApprovePlayer(socket: AuthenticatedSocket, data: { gameCode: string; playerName: string }): Promise<void> {
|
||||
try {
|
||||
const { gameCode, playerName } = data;
|
||||
const { gameCode, playerName } = JSON.parse(data as any);
|
||||
|
||||
// Verify that the requesting socket is the gamemaster
|
||||
const game = await this.gameRepository.findByGameCode(gameCode);
|
||||
@@ -434,7 +454,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleRejectPlayer(socket: AuthenticatedSocket, data: { gameCode: string; playerName: string; reason?: string }): Promise<void> {
|
||||
try {
|
||||
const { gameCode, playerName, reason } = data;
|
||||
const { gameCode, playerName, reason } = JSON.parse(data as any);
|
||||
|
||||
// Verify that the requesting socket is the gamemaster
|
||||
const game = await this.gameRepository.findByGameCode(gameCode);
|
||||
@@ -482,7 +502,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleJoinApproved(socket: AuthenticatedSocket, data: JoinGameData): Promise<void> {
|
||||
try {
|
||||
const { gameToken } = data;
|
||||
const { gameToken } = JSON.parse(data as any);
|
||||
|
||||
if (!gameToken) {
|
||||
socket.emit('game:error', { message: 'Game token is required' });
|
||||
@@ -560,7 +580,7 @@ export class GameWebSocketService {
|
||||
|
||||
private async handleDiceRoll(socket: AuthenticatedSocket, data: DiceRollData): Promise<void> {
|
||||
try {
|
||||
const { gameCode, diceValue } = data;
|
||||
const { gameCode, diceValue } = JSON.parse(data as any);
|
||||
|
||||
// Validate input
|
||||
if (!gameCode || !socket.gameCode || socket.gameCode !== gameCode) {
|
||||
@@ -772,14 +792,6 @@ export class GameWebSocketService {
|
||||
// Remove from pending players if they were pending
|
||||
await this.redisService.setRemove(`game_pending:${gameCode}`, playerName);
|
||||
|
||||
// If we have player ID, also clean up ID-based tracking
|
||||
if (playerId) {
|
||||
const game = await this.gameRepository.findByGameCode(gameCode);
|
||||
if (game?.id) {
|
||||
await this.redisService.setRemove(`active_players:${game.id}`, playerId);
|
||||
}
|
||||
}
|
||||
|
||||
logOther(`Cleaned up player data for ${playerName} in game ${gameCode}`);
|
||||
|
||||
} catch (error) {
|
||||
@@ -1276,7 +1288,6 @@ export class GameWebSocketService {
|
||||
if (gameId) {
|
||||
const gameIdKeys = [
|
||||
`game:${gameId}`, // Main game data
|
||||
`active_players:${gameId}`, // Active players set
|
||||
`game_turns:${gameId}` // Turn data by ID
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user