mirror of
https://github.com/tiennm99/gomoku.git
synced 2026-05-14 00:57:59 +00:00
cbc74c7813
Fixes the server log "gameover player N: unexpected Request_CreateRoom". Root cause: when ANY player leaves a room, leaveRoom broadcasts ClientExitResponse to ALL players in room.Players (so peers see who left). The broadcast fired CLIENT_EXIT on both the exiting client AND its peer. But the client's handlers treated every CLIENT_EXIT as "I exited" — transitioning to lobby, clearing gameState.roomId, hiding the HUD. Meanwhile the peer's server-side state machine was still in gameoverState. The peer then clicked Create Room from the (now wrongly shown) lobby, and the request arrived at gameoverState's default case. Client: - New services/client-exit-helpers.js with isSelfExit(data, clientId). exitClientId === 0 or missing → bare self-ack (home.ClientExit / watching.ClientExit / room-closed eject). exitClientId === clientId → our own leaveRoom broadcast loopback. Anything else → a peer left; stay in state. - game-state-service CLIENT_EXIT handler: only reset() when isSelfExit. - game-scene._onClientExit: only transition to MenuScene when isSelfExit; peer exits render a toast "<nickname> left the room" instead. - menu-ui.js module CLIENT_EXIT handler: only showLobby() when isSelfExit. Server: the client fix alone leaves a new hole — after a peer leaves a finished PVP room, the remaining player sits in gameoverState with a game-over modal and two buttons. "Play Again" would try to restart a PVP game with only one human; "Leave" still works. To close this hole cleanly: - state/waiting.go: add kickStaleRoomPeers helper. After a leaveRoom in gameoverState, if the room is a PVP room with < 2 remaining human players it's unplayable — push a synthetic Request_ClientExit onto each remaining peer's CmdCh. Their gameoverState goroutine wakes up, processes the synthetic exit, and returns StateHome in lockstep. - state/gameover.go: call kickStaleRoomPeers after leaveRoom in the ClientExit case. Tests: - Rename TestFlow_CreateRoomAfterOpponentForfeit → TestFlow_OpponentExit_KicksPeerFromGameover and rewrite to assert the auto-kick behavior: black leaves → white's gameoverState must return StateHome WITHOUT any test-driven CmdCh push. Then both players can create fresh rooms. Full suite + client build green.