# WebSocket Networking: First Iteration ## Scope The first networking iteration adds a Windows-only WebSocket transport using Boost.Asio and Boost.Beast. The goal of this iteration is connection and replication stability. It does not yet implement multiplayer commands, authentication, per-connection players, state deltas, or presentation-event replication. ## Runtime Architecture ### Server `WebsocketGameServer` wraps the headless `InternalGameServer`. - It accepts any WebSocket connection. - It sends the current complete game state immediately after connection. - It broadcasts the current complete state every five seconds. - Incoming WebSocket messages are read and discarded. - The authoritative simulation remains on the main server thread. - Network sessions only receive serialized state and never access `InternalGameServer` directly. The standalone server creates the existing fixed player ID `"player"` and does not enable the battle-zone test bot. ### Client `WebsocketGameClient` implements `IGameServer`. - It connects asynchronously to `ws://127.0.0.1:8080/`. - Received messages are queued by the network thread and applied on the game thread from `update()`. - It maintains an internal `InternalGameServer` replica so existing snapshot consumers and transitional runtime-state bindings continue to work. - `submit()` intentionally discards all commands. - `drainEvents()` returns no events. - Client-side save and load calls are ignored because persistence remains server-side. `RemoteGameServerHost` prepares local presentation resources and runtime locations against the replicated state. It does not advance authoritative simulation or write Lua/dialogue auxiliary state back to the server. ## Campaign Routing The graphical game uses stable router objects for `IGameServer` and `IGameServerHost`, allowing existing UI and runtime references to remain valid. When `NETWORK` is defined: - `battle_zone` uses `WebsocketGameClient` and `RemoteGameServerHost`. - Every other campaign uses `InternalGameServer` and `LocalGameServerHost`. The WebSocket client is created only when `battle_zone` is selected and is destroyed when that campaign is unloaded. ## JSON Protocol Messages use a versioned JSON envelope: ```json { "protocolVersion": 1, "type": "state", "payload": { "schemaVersion": 1 } } ``` The payload temporarily uses the existing `GameState::save()` representation. The client applies it through `InternalGameServer::load()`. Malformed JSON, unsupported protocol versions, unsupported message types, and invalid state payloads are logged and ignored. This temporary full-state format is expected to be replaced or separated from the persistence schema as command handling and production replication are implemented. ## Build Configuration Networking is enabled only for Windows: - `proj-windows/CMakeLists.txt` defines `NETWORK`, compiles the WebSocket client and remote host, and links `ws2_32` and `mswsock`. - `server/CMakeLists.txt` defines `NETWORK` for the Windows `GameServer`, compiles the WebSocket server, and links the Windows socket libraries. - Linux, Android, and Web builds do not define `NETWORK` and do not compile the network transport. The previous Web-build `NETWORK` definition was removed. ## Running Build the server: ```powershell cmake -S server -B server/build cmake --build server/build --config Debug --target GameServer ``` Run it from the repository root: ```powershell .\server\build\Debug\GameServer.exe --campaign battle_zone --location uni_exterior ``` The listener defaults to `0.0.0.0:8080`. It can be changed with: ```text --address IP --port N ``` Launch the Windows game and select `battle_zone`. The client connects to `127.0.0.1:8080`. Selecting another campaign continues to use the local server. ## Verification The implementation was verified with: - A successful Windows graphical-game build. - A successful Windows headless-server build. - Server state and protocol tests. - A WebSocket smoke test receiving the initial state and the next five-second broadcast. - A check that the shared `"player"` exists and the battle-zone test bot is not created for the network server. ## Current Limitations - All clients share the fixed player ID `"player"`. - Client commands are not sent to the server. - The server does not process commands. - State is sent as a complete snapshot rather than a delta. - There is no authentication, authorization, reconnect loop, or session identity. - Presentation events are not replicated. - The endpoint is hardcoded in the graphical client. - Multiplayer Lua and dialogue behavior remains unsupported.