# Headless GameServer This target runs the authoritative `InternalGameServer` without SDL, OpenGL, audio, Lua, or rendering dependencies. On Windows it exposes a deterministic lockstep session through a Boost.Beast WebSocket listener. ## Build Windows: ```powershell cmake -S server -B server/build cmake --build server/build --config Release --target GameServer ctest --test-dir server/build -C Release --output-on-failure ``` Linux: ```bash cmake -S server -B server/build -DCMAKE_BUILD_TYPE=Release cmake --build server/build --target GameServer --parallel ctest --test-dir server/build --output-on-failure ``` Eigen3 must either be installed or be available at `thirdparty/eigen-5.0.0`. The headless target reads ordinary filesystem resources only; ZIP-backed campaign loading belongs to the later content-loading milestone. Run until interrupted: ```bash ./server/build/GameServer ``` For a multi-configuration Windows build, the executable is normally `server/build/Release/GameServer.exe`. For smoke tests, `--ticks N` limits execution and `--no-sleep` skips the real-time delay. Start the multiplayer lockstep server: ```powershell .\server\build\Release\GameServer.exe --campaign battle_zone_multiplayer --location uni_exterior ``` The listener defaults to `ws://0.0.0.0:8080`. Launch the Windows graphical game afterward and select `battle_zone_multiplayer`; that campaign connects to `ws://127.0.0.1:8080`. Other campaigns continue to use the in-process server. The server sends one state snapshot when a player connects, then broadcasts one numbered command bundle every 100 ms. Bundles may be empty. Destination input is scheduled two ticks (200 ms) in the future. Tick IDs, rather than server or client wall-clock values, define simulation time. If `--location` is omitted, the campaign's configured start location is used. `--campaigns PATH` selects a different campaign registry. Content paths are resolved from the process working directory, so run from the repository root when using the bundled `resources/` tree. Available startup options: ```text --campaign ID --location ID --campaigns PATH --address IP --port N --tick-ms 100 --ticks N --no-sleep ``` Network mode requires a 100 ms tick; another `--tick-ms` value is rejected. The selected campaign's `networkPlayerSlots` lists pre-existing character IDs assigned to connections in order. `networkCompatibility` is a release token that must be changed whenever deterministic content changes; clients reject a different token. The bundled multiplayer Battle Zone has two slots (`player` and `player2`) and rejects additional clients. Disconnecting releases the slot. The bot's random autonomous controller is disabled in multiplayer. The graphical client executes presentation behavior after building its runtime `Location`; the headless content pass loads authoritative navigation, NPC, interactive-object, trigger, teleport, taxi, and animation metadata. Lua and dialogue-driven shared multiplayer behavior is not yet supported. ## Tests CTest covers: - repeated `LocationGameState::setup()` preserving mutable runtime state; - ticking a prepared location with zero players; - deterministic fixed-100 ms replay behavior; - protocol-v2 parsing, validation, target normalization, state hashing, and two-tick command ordering; - a WebSocket initial-state/slot/destination/tick integration test; - idle server startup; - headless loading of `battle_zone_multiplayer/uni_exterior`. The lockstep implementation currently targets identical executable and content builds. Diagnostic state hashes detect divergence, but there is no automatic checkpoint resynchronization or reconnect input history yet.