Add serverWorldState packet and GUI controls
Introduce a server-authoritative world-state packet to control weather and time from the dev server GUI. Adds protocol docs and message type (serverWorldState), a new Weather/Time tab in dev_server_app.py, server-side broadcasting in server_core.py, and preset utilities in server/world_state_presets.py. Plugin changes (F4TNetworking.cpp, F4TWorldStateSync.*) queue and apply incoming serverWorldState on the game thread, run `set gamehour` for all clients, and run `fw <8-digit-id>` on the assigned player 1 then force the host to relay a worldState snapshot. Also includes parsing/validation of hex form IDs, logging improvements, and minimal fake client handling. This ensures consistent server-driven time/weather and documents usage and presets.
This commit is contained in:
@@ -9,6 +9,7 @@ The first protocol should be simple and focused on player transform sync.
|
||||
- Welcome packet
|
||||
- Transform packet
|
||||
- World state packet (host time and weather) — see [`world-state.md`](world-state.md)
|
||||
- Server world state packet (dev GUI weather/time) — see [`server-world-state.md`](server-world-state.md)
|
||||
- Disconnect packet
|
||||
|
||||
## Future Packet Types
|
||||
|
||||
@@ -11,6 +11,7 @@ welcome
|
||||
transform
|
||||
worldState
|
||||
worldStateHost
|
||||
serverWorldState
|
||||
disconnect
|
||||
```
|
||||
|
||||
@@ -23,10 +24,12 @@ Current behavior:
|
||||
server, and broadcast to other connected clients.
|
||||
- `worldStateHost` is sent in `welcome` and when the host disconnects to
|
||||
reassign host to the lowest remaining `playerId`.
|
||||
- `serverWorldState` is sent by the server to all connected clients when the
|
||||
dev server GUI sets weather or time.
|
||||
- `disconnect` is sent by the server when a client disconnects.
|
||||
|
||||
The Fallout 4 plugin sends transform packets and receives `welcome`,
|
||||
`transform`, `worldState`, and `disconnect` packets. Received transforms are
|
||||
`transform`, `worldState`, `serverWorldState`, and `disconnect` packets. Received transforms are
|
||||
stored as plain remote-player state. Non-host clients apply received world state
|
||||
on the game thread.
|
||||
|
||||
@@ -39,6 +42,7 @@ welcome
|
||||
transform
|
||||
worldState
|
||||
worldStateHost
|
||||
serverWorldState
|
||||
disconnect
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Server World State Packet
|
||||
|
||||
Server-authoritative weather and time control from the dev server GUI.
|
||||
|
||||
## Authority
|
||||
|
||||
- **Time** (`timeHHmm`): sent to **all** clients; each runs `set gamehour to HHmm`.
|
||||
- **Weather** (`weatherConsoleArg`): sent to **all** clients, but only **player 1** runs `fw <8-digit-id>`. Player 1 should also be the world-state host so the usual `worldState` relay updates other clients.
|
||||
|
||||
## Packet Format
|
||||
|
||||
Time-only (all clients):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "serverWorldState",
|
||||
"timeHHmm": "1900",
|
||||
"serverTime": 1780212128.301
|
||||
}
|
||||
```
|
||||
|
||||
Weather (all clients receive; only player 1 acts):
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "serverWorldState",
|
||||
"weatherConsoleArg": "00148c45",
|
||||
"weatherFormId": "00148C45",
|
||||
"serverTime": 1780212128.301
|
||||
}
|
||||
```
|
||||
|
||||
## Field Definitions
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `type` | string | yes | Must be `"serverWorldState"` |
|
||||
| `timeHHmm` | string | no | 24-hour clock value for `set gamehour to HHmm` |
|
||||
| `weatherConsoleArg` | string | no | Exact argument for `fw` on player 1 (8-digit lowercase hex) |
|
||||
| `weatherFormId` | string | no | Relay form ID used in host `worldState` broadcast |
|
||||
| `serverTime` | number (double) | no | Relay timestamp |
|
||||
|
||||
## Client Apply Rules
|
||||
|
||||
- **Time:** all clients apply `set gamehour to HHmm` on the game thread.
|
||||
- **Weather:** only the client with assigned `playerId == 1` runs `fw <weatherConsoleArg>`.
|
||||
- Weather commands are scheduled on the F4SE game thread from the network receive path.
|
||||
- After player 1 runs `fw`, the world-state host immediately relays `worldState` with `weatherFormId`.
|
||||
|
||||
Edit `server/world_state_presets.py` so each preset uses the exact `fw` ID that works in your console (for example `0000015e`).
|
||||
|
||||
## Preset Weather Console Args
|
||||
|
||||
| Label | Default `fw` arg |
|
||||
|-------|------------------|
|
||||
| Clear | `00148c3c` |
|
||||
| Cloudy | `00148c42` |
|
||||
| Overcast | `00148c43` |
|
||||
| Fog | `00148c44` |
|
||||
| Rain | `00148c45` |
|
||||
| Radstorm | `00148c47` |
|
||||
| Glowing Sea | `001b9779` |
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
Older clients that do not handle `serverWorldState` ignore the packet safely.
|
||||
Reference in New Issue
Block a user