feat(api): add play again / reset lobby functionality #9

Open
opened 2026-04-18 08:24:28 +00:00 by forgejo-lila · 0 comments
Owner

Background

After a game finishes, the lobby status is set to 'finished' in the DB
via finishGame(). The MultiplayerScoreScreen has a "Play Again" button
that navigates back to /multiplayer/lobby/$code, which sends lobby:join
via WebSocket.

Currently handleLobbyJoin rejects connections where lobby.status !== 'waiting'.
This means "Play Again" always fails with a "Lobby is not in waiting state" error.

What needs to happen

When the host clicks "Play Again", the lobby needs to be reset to 'waiting'
status so players can reconnect and start a new game.

Proposed approach

Option A: Implicit reset on lobby:join
If a player sends lobby:join on a finished lobby they're a member of,
automatically reset the lobby status to 'waiting' and clear scores.

Option B: Explicit reset message
Add a new WsLobbyResetSchema client message. Host sends it, server
resets the lobby. Players then send lobby:join as normal.

Option B is cleaner — explicit intent, host controls the reset, consistent
with how lobby:start works. Option A is implicit and could cause unexpected
resets.

Scope

packages/shared/src/schemas/lobby.ts

  • Add WsLobbyResetSchema { type: 'lobby:reset', lobbyId }.
  • Add to WsClientMessageSchema.

apps/api/src/ws/handlers/lobbyHandlers.ts

  • Add handleLobbyReset — validates host, resets status to 'waiting',
    resets all player scores to 0, broadcasts lobby:state.

apps/api/src/models/lobbyModel.ts

  • Add resetLobby(lobbyId) — transaction: update status to 'waiting',
    reset all lobby_players.score to 0.

apps/web/src/components/multiplayer/MultiplayerScoreScreen.tsx

  • "Play Again" button sends lobby:reset before navigating back to lobby route.
  • Or host sees "Reset lobby" button, non-hosts see "Waiting for host to reset...".

apps/api/src/ws/handlers/lobbyHandlers.ts

  • Update handleLobbyJoin to accept 'waiting' status only — no change needed
    if reset happens before navigation.

Acceptance criteria

  • Host can reset a finished lobby back to waiting state.
  • All player scores reset to 0 on lobby reset.
  • Players who navigate back to lobby route see the waiting room correctly.
  • Non-host players see appropriate UI while waiting for host to reset.
  • A new game can be started after reset without issues.
  • apps/web/src/components/multiplayer/MultiplayerScoreScreen.tsx
  • apps/api/src/ws/handlers/lobbyHandlers.ts
  • apps/api/src/models/lobbyModel.ts
  • packages/shared/src/schemas/lobby.ts
## Background After a game finishes, the lobby status is set to `'finished'` in the DB via `finishGame()`. The `MultiplayerScoreScreen` has a "Play Again" button that navigates back to `/multiplayer/lobby/$code`, which sends `lobby:join` via WebSocket. Currently `handleLobbyJoin` rejects connections where `lobby.status !== 'waiting'`. This means "Play Again" always fails with a "Lobby is not in waiting state" error. ## What needs to happen When the host clicks "Play Again", the lobby needs to be reset to `'waiting'` status so players can reconnect and start a new game. ## Proposed approach **Option A: Implicit reset on lobby:join** If a player sends `lobby:join` on a finished lobby they're a member of, automatically reset the lobby status to `'waiting'` and clear scores. **Option B: Explicit reset message** Add a new `WsLobbyResetSchema` client message. Host sends it, server resets the lobby. Players then send `lobby:join` as normal. Option B is cleaner — explicit intent, host controls the reset, consistent with how `lobby:start` works. Option A is implicit and could cause unexpected resets. ## Scope **`packages/shared/src/schemas/lobby.ts`** - Add `WsLobbyResetSchema { type: 'lobby:reset', lobbyId }`. - Add to `WsClientMessageSchema`. **`apps/api/src/ws/handlers/lobbyHandlers.ts`** - Add `handleLobbyReset` — validates host, resets status to `'waiting'`, resets all player scores to 0, broadcasts `lobby:state`. **`apps/api/src/models/lobbyModel.ts`** - Add `resetLobby(lobbyId)` — transaction: update status to `'waiting'`, reset all `lobby_players.score` to 0. **`apps/web/src/components/multiplayer/MultiplayerScoreScreen.tsx`** - "Play Again" button sends `lobby:reset` before navigating back to lobby route. - Or host sees "Reset lobby" button, non-hosts see "Waiting for host to reset...". **`apps/api/src/ws/handlers/lobbyHandlers.ts`** - Update `handleLobbyJoin` to accept `'waiting'` status only — no change needed if reset happens before navigation. ## Acceptance criteria - [ ] Host can reset a finished lobby back to waiting state. - [ ] All player scores reset to 0 on lobby reset. - [ ] Players who navigate back to lobby route see the waiting room correctly. - [ ] Non-host players see appropriate UI while waiting for host to reset. - [ ] A new game can be started after reset without issues. ## Related - `apps/web/src/components/multiplayer/MultiplayerScoreScreen.tsx` - `apps/api/src/ws/handlers/lobbyHandlers.ts` - `apps/api/src/models/lobbyModel.ts` - `packages/shared/src/schemas/lobby.ts`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: forgejo-lila/lila#9
No description provided.