docs(multiplayer): reconcile review progress

This commit is contained in:
Josh Creek
2026-09-02 19:15:47 +01:00
parent 51f8008a38
commit 781cbc35aa
2 changed files with 11 additions and 10 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ The largest gap between this and a AAA-feeling product is presentation, not code
The single tracking document is **[`multiplayer-next.md`](multiplayer-next.md)** — architecture decisions, implementation evidence, and the current checklist all in one place. Server-authoritative multiplayer, prediction, ENet dedicated hosting, and the Phase 6 exported-server Docker/CI verification are implemented; the remaining gates are captured there.
Phase 7 begins with optional GodotSteam bootstrap and a transport boundary; direct-IP ENet remains fully supported. It also carries the **graphics/performance work** — the project has never been profiled, and `video_settings.gd` exposes only AA, glow and brightness while SDFGI, SSIL, SSAO and five shadow-casting lights are on by default and unreachable (see §5.5 there).
Phase 7 begins with optional GodotSteam bootstrap and a transport boundary; direct-IP ENet remains fully supported. Graphics controls are now implemented separately through the preset/vsync/FPS-cap/resolution-scale work described above; the remaining graphics gate is real low/mid-tier hardware profiling and visual QA (see §5.5 in the multiplayer tracker).
**Tasks 0.10.15, 0.180.25, 0.27, 0.29 are done** (see the Phase 0 table in `multiplayer-next.md` for what each one actually changed — several deviated from the original plan for concrete GDScript/Godot reasons recorded inline). Remaining, all blocked on **0.15b (profile, on reference hardware, in the live editor — not done)**: 0.16 (camera to `_process`), 0.17/0.17b/0.17c/0.17d (graphics presets, vsync, resolution scaling), **0.26 (bake the arena GI to retire SDFGI — the largest frame-time win available, costs no image quality since the arena is fully static)**, and 0.28 (physics separate-thread prototype, flagged as the riskiest task in the phase). These need a human at the editor with real hardware to profile and eyeball, not further code changes.
+10 -9
View File
@@ -12,7 +12,7 @@ those tasks assume; read them before picking up work in Phase 2 or later. §9
is a running gotchas list — check it before debugging something that looks
like a Godot/Jolt engine quirk, and add to it when you find a new one.
**Status: every task in Phases 06 is implemented and verified locally.** Both multiplayer milestones still need human verification — a playtest at ~100 ms RTT (Phase 4) and a real 3v3 session (Phase 5). Phase 6's public-internet gate is no longer blocked by the former display-name reclaim defect: allocated reconnects now use the signed identity, while the export, Docker, rotation/drain, and CI work remain complete. Phase 7's Steam foundation is in progress. **Phase 8 — matchmaking, ranked, and per-match server autoscaling — remains a 1.0 launch blocker and is partially implemented:** the Go domain policy, store boundaries, migration, supervisor, hardened Fleet baseline, testkit and offline end-to-end path are in place, while production API/DB/Redis/Steam/Agones wiring and runtime gates remain. It is the first phase to add a component outside the Godot project, and its design lives in [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md). The client has local-ship delta-rebase reconciliation, client-only ball touch prediction, adaptive input-depth signalling, and experimental remote present-time visuals; all server simulation, bot action/observation behaviour, collision resources, and tick rate remain unchanged. See the outstanding list immediately below for what is left and why, §7 for the implemented work and its evidence, and §11 for what is deliberately deferred.
**Status: every task in Phases 06 is implemented and verified locally.** Both multiplayer milestones still need human verification — a playtest at ~100 ms RTT (Phase 4) and a real 3v3 session (Phase 5). Phase 6's public-internet gate is no longer blocked for allocated reconnects, which use signed identity; direct/community reservations retain the documented display-name limitation. The export, Docker, rotation/drain, and CI work remain complete. Phase 7's Steam foundation is in progress. **Phase 8 — matchmaking, ranked, and per-match server autoscaling — remains a 1.0 launch blocker and is partially implemented:** the Go API/domain/store/Redis/allocator paths, migrations, supervisor, authenticated Kubernetes/Agones adapter, hardened Fleet baseline, testkit, and offline end-to-end path are in place. Production Steam identity/SDR, live cluster/public-network execution, release evidence, and human gates remain. It is the first phase to add a component outside the Godot project, and its design lives in [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md). The client has local-ship delta-rebase reconciliation, client-only ball touch prediction, adaptive input-depth signalling, and experimental remote present-time visuals; all server simulation, bot action/observation behaviour, collision resources, and tick rate remain unchanged. See the outstanding list immediately below for what is left and why, §7 for the implemented work and its evidence, and §11 for what is deliberately deferred.
---
@@ -1141,7 +1141,7 @@ New `--role=client-reconnect` grades the returning player: not a spectator, owns
| 7.2 `[D:7.1]` | **IN PROGRESS.** `NetTransport` boundary extracted with ENet and feature-gated `steam_transport.gd` (`SteamMultiplayerPeer`, SDR); advertising waits for `ISteamGameServer` work | `NetworkManager.host/join(..., transport)` selects explicitly; stock builds reject Steam without ENet fallback |
| 7.3 `[D:7.2]` `[P]` | **IN PROGRESS.** Server-browser UI and `ISteamMatchmakingServers` adapter remain intentionally unimplemented until the pinned GodotSteam client API is available; ENet direct-IP remains the supported browser-free path | No `server_browser.tscn` or fake Steam API has been added; implementation must wait for real Steam SDK/API access so Internet/LAN/favourites/history behavior can be verified against the actual service |
| 7.4 `[D:7.2]` `[P]` | **IN PROGRESS.** `TicketVerifier` now supports a synchronized backend ban decision before single-use ticket consumption; auth tickets in `hello``BeginAuthSession`, Steam identity in the roster and persistent ban list remain | `server/domain/auth.go` and adversarial tests reject banned identities without consuming their ticket and allow a later verification after unban; GodotSteam auth integration, server-side VAC state and durable ban storage remain |
| 7.5 `[D:7.2]` `[P]` | **IN PROGRESS.** `SteamBootstrap` gates initialization on the `steam` feature, `SteamMultiplayerPeer` class and Steam singleton; explicit Steam selection fails closed, while ENet remains the default and never becomes an implicit fallback | `test_net_transport.gd` proves stock builds keep ENet available and reject unavailable Steam requests without returning an ENet peer; custom Steam client/server export smoke remains blocked on pinned GodotSteam binaries, and full ENet runtime verification remains blocked on the absent Godot executable |
| 7.5 `[D:7.2]` `[P]` | **IN PROGRESS.** `SteamBootstrap` gates initialization on the `steam` feature, `SteamMultiplayerPeer` class and Steam singleton; explicit Steam selection fails closed, while ENet remains the default and never becomes an implicit fallback | `test_net_transport.gd` proves stock builds keep ENet available and reject unavailable Steam requests without returning an ENet peer; the full local ENet multi-process gate passes with Godot 4.7.1, while the custom Steam client/server export smoke remains blocked on pinned GodotSteam binaries |
| 7.6 `[D:7.4]` | **IN PROGRESS.** Pure Go `AuthCoordinator` models pending/accepted/rejected/cancelled backend auth sessions around the single-use verifier, including maintenance expiry sweeping; `store.PostgresSessions` persists only token digests; the authenticated API issues sessions only from an injected verified-identity provider; Godot `ControlPlaneClient.login_steam()` now submits only the Web API ticket, validates the opaque response and stores the session in memory | `server/domain/auth.go`, `server/store/session_sql.go`, `server/api/service.go`, `control_plane_client.gd` and adversarial tests keep identity unavailable while pending, reject cancellation/expiry/wrong-attempt/replay, expire abandoned attempts at the boundary, release identity only after verifier success, reject invalid session inputs/extra identity fields, prove API delegation, validate ticket/session header boundaries and issue opaque sessions; real Steam BeginAuthSession/EndAuthSession adapter, login UI and live PostgreSQL/session integration remain |
| 7.7 `[D:7.1]` `[P]` | Obtain the production App ID, publisher key, SDR coordinator SDK/signing approval, certificates and hosted-data-centre support from Valve | Production prerequisites and rotation owners are recorded; no Spacewar credential or development certificate can reach a release build |
| 7.8 `[D:7.6,7.7]` | Ticketed Hosted Dedicated Server SDR: routing registration, coordinator-issued player→server relay tickets, client ticket installation, reconnect and expiry | Two real accounts complete and reconnect to an assigned dedicated match through SDR; server/player IPs are not exposed; ENet gates remain green |
@@ -1168,11 +1168,12 @@ and players find it by IP or (7.3) the server browser. Matchmaking makes the
**allocated for that one match** and destroyed after. Both models ship; they
are different playlists, not a replacement.
**Hard dependency on 7.6 and 7.8.** Slot reclaim is keyed by display name
today. A rating attached to a spoofable identity is farmed trivially, so no
queue ships before single-use verified identity lands. Production allocation
also depends on the ticketed Hosted Dedicated Server SDR route; ENet remains
the local/CI/community transport, not a silent production fallback.
**Hard dependency on 7.6 and 7.8.** The local allocated path now binds slot
reclaim to a control-plane-signed player identity and locks its team/slot pair,
but production Steam ticket verification is still required before a rating can
be trusted. Production allocation also depends on the ticketed Hosted Dedicated
Server SDR route; ENet remains the local/CI/community transport, not a silent
production fallback.
#### 8A — Architecture, contracts and data
@@ -1495,11 +1496,11 @@ operation is idempotent and does not affect the other participants' requeue;
timeout-derived cooldown recording now uses the same durable penalty path,
with deterministic per-proposal/player IDs for replay safety.
### Current local completion index (2026-09-01)
### Current local completion index (2026-09-02)
The following Phase 8 slices have local implementation and verification evidence in this document: 8.29 dynamic allocated launch flags and endpoint handling; 8.30 allocator claim/reconciliation including provider-outcome recovery fencing and durable arena identity (migrations 00080009); 8.31 signed assignment/roster validation; 8.35 initial-connect no-show and casual bot policy; 8.36 controlled drain and shutdown acknowledgment; 8.398.43 client state, assignment, profile, recovery, and idempotent action retry; 8.44 structured observability and content-aware redaction; 8.45 bounded API metrics export plus optional Prometheus scrape/alert rules; 8.46 normal/race/vet/fuzz coverage; 8.478.48 offline/testkit/Compose coverage; 8.50 atomic stalled-allocation recovery notifications; 8.51 the 10,000-client API load boundary; 8.52 the opt-in per-replica plus shared PostgreSQL regional allocator quota; and 8.53 the fail-closed promotion validator. Their remaining acceptance text is infrastructure or production dependent where explicitly noted below the corresponding row.
The following are not locally certifiable from this workspace and remain open prerequisites rather than silently “done”: Valve/GodotSteam credentials and hosted SDR (7.17.8), live PostgreSQL/Redis execution where Docker is unavailable, live Agones/kind lifecycle (8.308.38, 8.49), public-network chaos/load/cost/release gates (8.508.53), and real-hardware graphics profiling (0.15b onward). `make verify-kind-agones` is the committed runner for 8.49; its response validator is unit-tested against malformed/ambiguous allocation payloads, but the runner still requires a running Docker daemon plus kind, kubectl, and Helm. `TODO.md`s AI-training and presentation tasks remain separate from multiplayer and are not marked by this index.
The following are not locally certifiable from this workspace and remain open prerequisites rather than silently “done”: Valve/GodotSteam credentials and hosted SDR (7.17.8), reruns of disposable PostgreSQL/Redis gates while Docker storage is exhausted, live Agones/kind lifecycle (8.308.38, 8.49), public-network chaos/load/cost/release gates (8.508.53), and real-hardware graphics profiling (0.15b onward). `make verify-kind-agones` is the committed runner for 8.49; its response validator is unit-tested against malformed/ambiguous allocation payloads, but this machine still lacks kind and Helm and cannot initialize another Docker database until storage is reclaimed. `TODO.md`s AI-training and presentation tasks remain separate from multiplayer and are not marked by this index.
The live control-plane integration was retried on 2026-09-01 after Docker Desktop became available, but the disposable `postgres:17-alpine` container failed during `initdb` with `No space left on device`; Docker reported 10.2 GB of images and 3.3 GB of volumes. No live integration pass is claimed until storage is reclaimed and the gate completes.