v0.4.0 — multiplayer Phases 0 and 1: seat and player split apart, turn state per player, the page behind a Session, and eight seat/player mix-ups fixed with tests that fail without them

This commit is contained in:
Jesse
2026-08-13 14:06:02 -04:00
parent 216006b091
commit 49f8504b05
34 changed files with 1743 additions and 526 deletions
+10 -7
View File
@@ -115,13 +115,16 @@ trains move and wrecks happen while the Superintendent rules on clearances.
That means the server must push. A request/response API alone would leave four players polling to
watch a fifth switch cars.
**WebSocket, with the HTTP endpoints alongside it** for lobby operations (list games, create, join)
where a request/response shape is the natural fit. Server-Sent Events would also serve, since the
push is nearly one-directional and intents are rare enough to send over HTTP — worth keeping in mind
if the eventual stack makes SSE materially simpler.
**Server-Sent Events, with HTTP POST alongside** for lobby operations and for intents, where a
request/response shape is the natural fit. This paragraph originally leaned the other way, toward
WebSocket with SSE as the fallback; it was settled the other way in
[`multiplayer.md`](multiplayer.md) D5, because the push is nearly one-directional, intents are rare,
and SSE reconnects itself through anything in the path without a protocol upgrade to negotiate.
What matters more than the choice: **every state change reaches clients as an event on one ordered
stream**. Clients apply events in order and never mutate state locally in a way that could drift.
What matters more than the choice: **every state change reaches clients on one ordered stream**, and
clients never mutate state locally in a way that could drift. What travels on that stream is a
redacted `Frame`, not the raw events — see `multiplayer.md` D2/D3 for why one reducer and one
redaction chokepoint beat shipping the history to every client.
---
@@ -159,7 +162,7 @@ Keep the **rules engine** free of any knowledge of networking, storage, or playe
│
game session owns one game's state, applies intents, emits events
▲
lobby / transport connections, reconnection, persistence, HTTP + WebSocket
lobby / transport connections, reconnection, persistence, HTTP POST + SSE
```
The rules engine being pure and deterministic is what makes the whole thing testable — you can drive