fix: per-socket state with drawer-only wordChoices to prevent race on lobby→play nav

This commit is contained in:
PM
2026-05-04 15:32:03 +00:00
parent 4b98d07069
commit ce43e6f6aa
2 changed files with 24 additions and 2 deletions
+15 -1
View File
@@ -59,7 +59,8 @@ function makeRoom({ code, hostId, mode, settings }) {
}; };
} }
function publicRoomState(room) { function publicRoomState(room, viewerId) {
const isViewerDrawer = !!(viewerId && room.skribbl && room.skribbl.drawerId === viewerId);
return { return {
code: room.code, code: room.code,
hostId: room.hostId, hostId: room.hostId,
@@ -84,6 +85,19 @@ function publicRoomState(room) {
phase: room.skribbl.phase, // 'choosing' | 'drawing' | 'between' phase: room.skribbl.phase, // 'choosing' | 'drawing' | 'between'
endsAt: room.skribbl.endsAt, endsAt: room.skribbl.endsAt,
solvedIds: [...(room.skribbl.solvedIds || [])], solvedIds: [...(room.skribbl.solvedIds || [])],
// Drawer-only: surface current word choices in the snapshot so a
// late-mounted play page (after lobby→/play navigation) can render
// the pick modal even if the original skribbl:wordChoices event
// was emitted before the listener was attached.
wordChoices:
isViewerDrawer && room.skribbl.phase === "choosing"
? room.skribbl.wordChoices
: null,
// Drawer-only: reveal the actual word so they know what to draw.
word:
isViewerDrawer && room.skribbl.phase === "drawing"
? room.skribbl.word
: null,
} }
: null, : null,
gartic: room.gartic gartic: room.gartic
+9 -1
View File
@@ -10,7 +10,15 @@ function escape(text) {
} }
function broadcastState(io, room) { function broadcastState(io, room) {
io.to(room.code).emit("room:state", G.publicRoomState(room)); // Per-socket emission so we can include drawer-only data
// (wordChoices during choosing, secret word during drawing) in the
// snapshot of the right viewer without leaking it to others.
for (const player of room.players) {
if (!player.socketId) continue;
const sock = io.sockets.sockets.get(player.socketId);
if (!sock) continue;
sock.emit("room:state", G.publicRoomState(room, player.id));
}
} }
function chatSystem(io, room, text) { function chatSystem(io, room, text) {