From 9f105ada5e499d0f4a96a758caaf9a739aa9390e Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Thu, 2 Apr 2026 13:56:24 +0200 Subject: [PATCH] fix(games): send room state directly to joining client Bun's ws.publish() excludes the sender, so the joining client never received the PLAYER_JOINED message and stayed stuck on the connecting spinner. Now sends the message directly to the joiner via ctx.send in addition to publishing to other room subscribers. Co-Authored-By: Claude Opus 4.6 (1M context) --- api/src/games/ws-handler.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api/src/games/ws-handler.ts b/api/src/games/ws-handler.ts index c4305ee..3a7704c 100644 --- a/api/src/games/ws-handler.ts +++ b/api/src/games/ws-handler.ts @@ -37,11 +37,15 @@ export function handleGameMessage(msg: GameWsClientMessage, ctx: WsContext): voi ctx.subscribe(`room:${msg.roomId}`); const playerInfo: PlayerInfo = { discordId: ctx.playerId, username: ctx.username }; - ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "PLAYER_JOINED", roomId: msg.roomId, player: playerInfo, as: msg.as })); + const joinedMsg = JSON.stringify({ type: "PLAYER_JOINED", roomId: msg.roomId, player: playerInfo, as: msg.as }); + ctx.publish(`room:${msg.roomId}`, joinedMsg); + ctx.send(joinedMsg); if (result.started) { const spectatorView = roomManager.getSpectatorView(msg.roomId); - ctx.publish(`room:${msg.roomId}`, JSON.stringify({ type: "GAME_STARTED", roomId: msg.roomId, state: spectatorView })); + const startedMsg = JSON.stringify({ type: "GAME_STARTED", roomId: msg.roomId, state: spectatorView }); + ctx.publish(`room:${msg.roomId}`, startedMsg); + ctx.send(startedMsg); } else { const room = roomManager.getRoom(msg.roomId); if (room && room.status === "playing") {