Skip to content

Pre-Game Lobby State #887

@eshaffer321

Description

@eshaffer321

Parent Issue

Part of #885 (Online Networked Multiplayer)

Overview

The server needs to manage a pre-game state where players join a game room and select heroes before the game initializes. Currently GameServer.initializeGame() is called immediately with all player/hero IDs upfront. For online play, players trickle in and pick heroes one at a time.

Current State

  • GameServer.initializeGame(playerIds, heroIds, scenarioId) requires all players and heroes upfront
  • No concept of a "waiting for players" state
  • Setup screen currently runs client-side and passes a complete GameConfig to GameProvider

Acceptance Criteria

  • Game room has a lobby phase before the game starts
  • Creator sets player count (2-4) when creating the room
  • Players join the room and are assigned a player slot
  • Each player selects their own hero from available (unselected) heroes
  • Server tracks which slots are filled and which heroes are taken
  • Server broadcasts lobby state to all connected players (who's joined, hero selections)
  • Game auto-initializes when all slots have players with selected heroes
  • Late joins rejected once game has started (or all slots filled)

Bootstrap & Identity Requirements

  • Room creation flow is explicitly defined in protocol (creator bootstrap), not implicit in server internals
  • Server assigns stable player identity for lobby/game (playerId and/or session token)
  • Join/rejoin is idempotent for the same session (refresh does not create duplicate slots)
  • Lobby identity persists through transition from lobby to started game

Lobby State Shape

interface LobbyState {
  gameId: string;
  playerCount: number;  // Set by creator
  slots: LobbySlot[];
}

interface LobbySlot {
  playerId: string | null;  // null = open slot
  heroId: HeroId | null;    // null = not yet selected
  ready: boolean;
}

Message Protocol (Lobby Phase)

// Client → Server
{ type: "join_game" }
{ type: "select_hero", heroId: HeroId }

// Server → Client
{ type: "lobby_update", lobby: LobbyState }
{ type: "game_started" }  // Transition to game phase
{ type: "error", message: string }

Key Files

Create:

  • packages/server/src/GameLobby.ts — lobby state management

Modify:

  • packages/server/src/WebSocketServer.ts — route lobby messages before game start

Dependencies

Test Plan

  • Creator sets player count, first slot is assigned to them
  • Second player joins, gets assigned next open slot
  • Hero selection updates broadcast to all players
  • Duplicate hero selection prevented
  • Game initializes automatically when all heroes selected
  • Rejects joins when game is full or already started
  • Refresh/reconnect rebinds to existing slot instead of creating duplicate player

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1-highImportant for core experiencearea:multiplayerMultiplayer functionalitycomplexity:mediumModerate effort, multiple files or considerationsfeatureNew functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions