game workflow corrected #93
@@ -970,6 +970,8 @@ socket.on('game:ended', {
|
||||
message: string;
|
||||
finalPositions: PlayerPosition[];
|
||||
timestamp: string;
|
||||
reason?: string; // Optional: 'gamemaster_left' if GM disconnected
|
||||
gamemasterName?: string; // Optional: GM name if GM left
|
||||
});
|
||||
|
||||
// Server → All Players: Cleanup complete
|
||||
@@ -980,6 +982,36 @@ socket.on('game:cleanup-complete', {
|
||||
});
|
||||
```
|
||||
|
||||
**Game End Scenarios**:
|
||||
|
||||
1. **Normal Win** (Player reaches position 100):
|
||||
```typescript
|
||||
{
|
||||
winner: "player-uuid",
|
||||
winnerName: "Alice",
|
||||
message: "🎉 Alice won the game! Congratulations!",
|
||||
finalPositions: [...],
|
||||
timestamp: "2025-11-06T..."
|
||||
}
|
||||
```
|
||||
|
||||
2. **Gamemaster Disconnect** (Game cancelled):
|
||||
```typescript
|
||||
{
|
||||
reason: "gamemaster_left",
|
||||
gamemasterName: "Bob",
|
||||
message: "🎭 Gamemaster Bob left. Game has ended.",
|
||||
timestamp: "2025-11-06T..."
|
||||
}
|
||||
```
|
||||
|
||||
**Behavior**:
|
||||
- Game immediately cancelled when gamemaster disconnects
|
||||
- All players notified via `game:ended` event
|
||||
- Database updated: `state = CANCELLED`, `enddate = now`
|
||||
- All Redis data and socket connections cleaned up
|
||||
- No winner recorded (game didn't complete normally)
|
||||
|
||||
---
|
||||
|
||||
#### Error Events
|
||||
|
||||
Binary file not shown.
@@ -1139,6 +1139,36 @@ export class GameWebSocketService {
|
||||
// If the socket was in a game, handle cleanup
|
||||
if (socket.gameCode && socket.playerName) {
|
||||
try {
|
||||
// Check if this player is the gamemaster
|
||||
const game = await this.gameRepository.findByGameCode(socket.gameCode);
|
||||
const isGamemaster = game && socket.userId && game.createdby === socket.userId;
|
||||
|
||||
// If gamemaster leaves, end the game immediately
|
||||
if (isGamemaster && game) {
|
||||
logOther(`Gamemaster ${socket.playerName} left game ${socket.gameCode}, ending game`);
|
||||
|
||||
const gameRoomName = `game_${socket.gameCode}`;
|
||||
|
||||
// Notify all players
|
||||
this.io.of('/game').to(gameRoomName).emit('game:ended', {
|
||||
reason: 'gamemaster_left',
|
||||
gamemasterName: socket.playerName,
|
||||
message: `🎭 Gamemaster ${socket.playerName} left. Game has ended.`,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Update database
|
||||
await this.gameRepository.update(game.id, {
|
||||
state: GameState.CANCELLED,
|
||||
enddate: new Date()
|
||||
});
|
||||
|
||||
// Clean up all game data
|
||||
await this.cleanupGameData(socket.gameCode, game.id);
|
||||
|
||||
return; // Exit early, no need for further cleanup
|
||||
}
|
||||
|
||||
// Clean up any pending card answer
|
||||
if (socket.userId) {
|
||||
const pendingCard = await this.getPendingCard(socket.gameCode, socket.userId);
|
||||
@@ -2236,7 +2266,7 @@ export class GameWebSocketService {
|
||||
if (game) {
|
||||
await this.gameRepository.update(game.id, {
|
||||
state: GameState.FINISHED,
|
||||
winner: winnerId,
|
||||
winnerId: winnerId,
|
||||
enddate: new Date()
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user