# Headless GameServer This target runs the authoritative `InternalGameServer` without SDL, OpenGL, audio, Lua, or rendering dependencies. On Windows it exposes the state 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 first multiplayer transport iteration: ```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 broadcasts an initial full state and then one every five seconds. Client commands are intentionally discarded in this iteration. 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 N --ticks N --no-sleep ``` The graphical client executes Lua/dialogue behavior after building its runtime `Location`; the headless content pass loads authoritative navigation, NPC, interactive-object, trigger, teleport, taxi, and animation metadata only. The standalone WebSocket lifecycle creates the existing shared `"player"` so the graphical client can render its local character. It does not create the battle-zone test bot. ## Tests CTest covers: - repeated `LocationGameState::setup()` preserving mutable runtime state; - ticking a prepared location with zero players; - idle server startup; - headless loading of `battle_zone_multiplayer/uni_exterior`.