From ef7f15c4acbab02fc60962e5f5f7479a38d7c0c9 Mon Sep 17 00:00:00 2001 From: Bernard Gawor Date: Wed, 28 Jan 2026 15:02:27 +0100 Subject: [PATCH 1/3] check game players count by asking fishjam --- .../packages/backend/src/game/room.ts | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/deep-sea-stories/packages/backend/src/game/room.ts b/deep-sea-stories/packages/backend/src/game/room.ts index 6f11be5..c8c7390 100644 --- a/deep-sea-stories/packages/backend/src/game/room.ts +++ b/deep-sea-stories/packages/backend/src/game/room.ts @@ -66,7 +66,8 @@ export class GameRoom { } async addPlayer(name: string): Promise<{ peer: Peer; peerToken: string }> { - if (this.players.size >= ROOM_PLAYERS_LIMIT) { + const roomPlayersCount = await this.getPlayersCount(); + if (roomPlayersCount >= ROOM_PLAYERS_LIMIT) { throw new GameRoomFullError(); } const { peer, peerToken } = await this.fishjamClient.createPeer( @@ -242,4 +243,35 @@ export class GameRoom { await new Promise((resolve) => setTimeout(resolve, 500)); return { agent, agentId: peer.id }; } + + private async getPlayersCount(): Promise { + try { + const room = await this.fishjamClient.getRoom(this.roomId); + const webrtcPlayers = room.peers.filter((peer) => peer.type === 'webrtc'); + const playersCount = webrtcPlayers.length; + this.reconcilePlayersCount(webrtcPlayers); + return playersCount; + } catch (e) { + console.error(`Error fetching room info for room ${this.roomId}:`, e); + return this.players.size; + } + } + + private reconcilePlayersCount(webrtcPlayers: Peer[]) { + if (webrtcPlayers.length !== this.players.size) { + console.warn( + `Discrepancy in player count for room ${this.roomId}: Fishjam reports ${webrtcPlayers.length}, local state has ${this.players.size}. This most probably means some peerDisconnected events were missed.`, + ); + const webrtcPeerIds = new Set(webrtcPlayers.map((p) => p.id)); + for (const localPeerId of this.players.keys()) { + if (!webrtcPeerIds.has(localPeerId)) { + console.log( + `Reconciling: removing peer ${localPeerId} from local state of room ${this.roomId}`, + ); + this.players.delete(localPeerId); + this.gameSession?.removePlayer(localPeerId); + } + } + } + } } From edce0d4d0c8514b7b814867ac9b06077b3c12d32 Mon Sep 17 00:00:00 2001 From: Bernard Gawor Date: Wed, 28 Jan 2026 15:56:50 +0100 Subject: [PATCH 2/3] copiilot suggestions --- .../packages/backend/src/game/room.ts | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/deep-sea-stories/packages/backend/src/game/room.ts b/deep-sea-stories/packages/backend/src/game/room.ts index c8c7390..3e3cb8f 100644 --- a/deep-sea-stories/packages/backend/src/game/room.ts +++ b/deep-sea-stories/packages/backend/src/game/room.ts @@ -66,7 +66,7 @@ export class GameRoom { } async addPlayer(name: string): Promise<{ peer: Peer; peerToken: string }> { - const roomPlayersCount = await this.getPlayersCount(); + const roomPlayersCount = await this.getAndReconcilePlayersCount(); if (roomPlayersCount >= ROOM_PLAYERS_LIMIT) { throw new GameRoomFullError(); } @@ -244,34 +244,48 @@ export class GameRoom { return { agent, agentId: peer.id }; } - private async getPlayersCount(): Promise { + private async getAndReconcilePlayersCount(): Promise { try { const room = await this.fishjamClient.getRoom(this.roomId); const webrtcPlayers = room.peers.filter((peer) => peer.type === 'webrtc'); - const playersCount = webrtcPlayers.length; this.reconcilePlayersCount(webrtcPlayers); - return playersCount; + return webrtcPlayers.length; } catch (e) { console.error(`Error fetching room info for room ${this.roomId}:`, e); return this.players.size; } } - private reconcilePlayersCount(webrtcPlayers: Peer[]) { - if (webrtcPlayers.length !== this.players.size) { - console.warn( - `Discrepancy in player count for room ${this.roomId}: Fishjam reports ${webrtcPlayers.length}, local state has ${this.players.size}. This most probably means some peerDisconnected events were missed.`, - ); - const webrtcPeerIds = new Set(webrtcPlayers.map((p) => p.id)); - for (const localPeerId of this.players.keys()) { - if (!webrtcPeerIds.has(localPeerId)) { - console.log( - `Reconciling: removing peer ${localPeerId} from local state of room ${this.roomId}`, - ); - this.players.delete(localPeerId); - this.gameSession?.removePlayer(localPeerId); + private async reconcilePlayersCount(webrtcPlayers: Peer[]) { + try { + if (webrtcPlayers.length !== this.players.size) { + console.warn( + `Discrepancy in player count for room ${this.roomId}: Fishjam reports ${webrtcPlayers.length}, local state has ${this.players.size}. This most probably means some peerDisconnected events were missed.`, + ); + const webrtcPeerIds = new Set(webrtcPlayers.map((p) => p.id)); + for (const localPeerId of this.players.keys()) { + if (!webrtcPeerIds.has(localPeerId)) { + console.log( + `Reconciling: removing peer ${localPeerId} from local state of room ${this.roomId}`, + ); + this.players.delete(localPeerId); + this.gameSession?.removePlayer(localPeerId); + } + } + for (const fishjamPeer of webrtcPlayers) { + if (!this.players.has(fishjamPeer.id)) { + await this.fishjamClient.deletePeer(this.roomId, fishjamPeer.id); + console.log( + `Reconciling: removing unknown peer ${fishjamPeer.id} from Fishjam room ${this.roomId}`, + ); + } } } + } catch (e) { + console.error( + `Error reconciling players count for room ${this.roomId}:`, + e, + ); } } } From 52eed9dddf7da2265feacbf1bf8ffaec180a5fc4 Mon Sep 17 00:00:00 2001 From: Bernard Gawor Date: Wed, 28 Jan 2026 22:44:35 +0100 Subject: [PATCH 3/3] comment suggestion --- .../packages/backend/src/game/room.ts | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/deep-sea-stories/packages/backend/src/game/room.ts b/deep-sea-stories/packages/backend/src/game/room.ts index 3e3cb8f..4c41de9 100644 --- a/deep-sea-stories/packages/backend/src/game/room.ts +++ b/deep-sea-stories/packages/backend/src/game/room.ts @@ -258,27 +258,28 @@ export class GameRoom { private async reconcilePlayersCount(webrtcPlayers: Peer[]) { try { - if (webrtcPlayers.length !== this.players.size) { - console.warn( - `Discrepancy in player count for room ${this.roomId}: Fishjam reports ${webrtcPlayers.length}, local state has ${this.players.size}. This most probably means some peerDisconnected events were missed.`, - ); - const webrtcPeerIds = new Set(webrtcPlayers.map((p) => p.id)); - for (const localPeerId of this.players.keys()) { - if (!webrtcPeerIds.has(localPeerId)) { - console.log( - `Reconciling: removing peer ${localPeerId} from local state of room ${this.roomId}`, - ); - this.players.delete(localPeerId); - this.gameSession?.removePlayer(localPeerId); - } + if (webrtcPlayers.length === this.players.size) { + return; + } + console.warn( + `Discrepancy in player count for room ${this.roomId}: Fishjam reports ${webrtcPlayers.length}, local state has ${this.players.size}. This most probably means some peerDisconnected events were missed.`, + ); + const webrtcPeerIds = new Set(webrtcPlayers.map((p) => p.id)); + for (const localPeerId of this.players.keys()) { + if (!webrtcPeerIds.has(localPeerId)) { + console.log( + `Reconciling: removing peer ${localPeerId} from local state of room ${this.roomId}`, + ); + this.players.delete(localPeerId); + this.gameSession?.removePlayer(localPeerId); } - for (const fishjamPeer of webrtcPlayers) { - if (!this.players.has(fishjamPeer.id)) { - await this.fishjamClient.deletePeer(this.roomId, fishjamPeer.id); - console.log( - `Reconciling: removing unknown peer ${fishjamPeer.id} from Fishjam room ${this.roomId}`, - ); - } + } + for (const fishjamPeer of webrtcPlayers) { + if (!this.players.has(fishjamPeer.id)) { + await this.fishjamClient.deletePeer(this.roomId, fishjamPeer.id); + console.log( + `Reconciling: removing unknown peer ${fishjamPeer.id} from Fishjam room ${this.roomId}`, + ); } } } catch (e) {