Implemented the real server
This commit is contained in:
1 parent
931236bec0
commit
075750442f
22 files changed
+1130
-44
No files matched your search
@@ -0,0 +1,143 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user