From 3573da12e1ad8386965be87d7d11ef287e84da0e Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 22 Jul 2026 17:59:38 +0200 Subject: [PATCH] docs(architecture): plan session and player composition --- ...lice-8-checkpoint-i-ordered-composition.md | 4 +- ...ow-slice-8-checkpoint-i7-session-player.md | 185 ++++++++++++++++++ 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md diff --git a/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md index a26aa0b1..98cf96ee 100644 --- a/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md +++ b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md @@ -281,7 +281,9 @@ ledger only after the complete pipeline is live. under the same ownership contract. `GameWindow.cs` is 2,840 raw lines; the App gate passes 3,407 tests / 3 intentional skips and the complete Release suite passes 7,779 tests / 5 intentional skips. I.7 session, streaming, and - hydration composition is the active cut. + hydration composition is the active cut; its ownership, rollback, and gate + contract is + [`2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md`](2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md). Checkpoint I remains active until I.9 closes the complete nine-phase pipeline. ## 6. Automated acceptance diff --git a/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md new file mode 100644 index 00000000..b5db9889 --- /dev/null +++ b/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i7-session-player.md @@ -0,0 +1,185 @@ +# GameWindow Slice 8 — Checkpoint I.7 Session and Player Composition + +**Status:** Active + +**Parent:** `2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md` + +**Scope:** Ordered-composition Phase 7 only + +## 1. Outcome + +Move the complete streaming, session, hydration, local-player, and teleport +construction body out of `GameWindow.OnLoad` without changing accepted +movement, network, world-reveal, combat, portal, or render-frame behavior. +`GameWindow` remains a write-only publication surface and shutdown shell. + +This is a structural ownership move. It does not alter retail algorithms or +add a divergence-register row. + +## 2. Exact production order + +`SessionPlayerCompositionPhase` preserves the current order: + +1. resolve near/far streaming radii from the immutable quality snapshot and + legacy override; +2. construct and start `LandblockStreamer` under immediate rollback ownership; +3. construct `StreamingController`, origin recentering, runtime settings + targets, and `WorldRevealCoordinator`; +4. construct the network-update bridge, sealed-dungeon classifier, + projection materializer, and world-origin coordinator; +5. construct and bind `LiveSessionController` plus local physics timestamps; +6. construct teardown, deletion, hydration, network-update, liveness, and + inbound-session owners; +7. bind component teardown, landblock hydration, parent acceptance, + same-generation network updates, entity-ready, and appearance-applied; +8. bind live combat operations; +9. construct mouse-look/gameplay input, streaming-frame, effect-frame, + spatial reconciliation, local animation/shadow/projection/frame, and + live-object frame owners; +10. construct player-mode and auto-entry owners and bind developer commands; +11. transfer the prepared portal tunnel into the sole local-teleport owner; +12. bind the teleport network sink and retained selection view plane; +13. publish one complete `SessionPlayerResult` and transfer rollback ownership. + +No live connection starts in this phase. Terminal session start remains Phase +9 so a server cannot publish into a partial frame graph. + +## 3. Typed inputs and outputs + +`SessionPlayerDependencies` contains only stable App owners and state sources. +It never stores `GameWindow` or accepts a callback to a substantial window +method. Phase results supply content, render, interaction, and live-presentation +owners directly. + +`SessionPlayerResult` carries the exact owners required by Phase 8 and +shutdown: + +- streamer, streaming controller, origin recenter, and world reveal; +- live-session, hydration, network-update, liveness, and inbound-session + controllers; +- gameplay input, streaming-frame, local animation/shadow, live-object frame, + player-mode, and auto-entry owners; +- local teleport owner; +- one named runtime-binding aggregate. + +`IGameWindowSessionPlayerPublication` publishes those exact identities only +after all mandatory resources and binds succeed. Replacement is rejected +before any field changes. + +## 4. Focused owners and seams + +### 4.1 Spawn-claim classifier + +Move the memoized indoor spawn-claim range check from `GameWindow` into +`DatSpawnClaimHydrationClassifier`. It retains the exact cell-number boundary, +DAT lock, and one-claim memoization. The world-reveal coordinator receives its +typed `IsUnhydratable` method rather than a window callback. + +### 4.2 Runtime bindings + +`SessionPlayerRuntimeBindings` owns named exact-owner leases and releases them +in reverse order. Successful releases are removed immediately; failed releases +remain retryable without replaying completed work. + +The aggregate owns: + +- retained-UI live-session authority; +- runtime settings targets; +- live parent acceptance; +- hydration network bridge; +- exact `EquippedChildRenderController.EntityReady` delegate; +- exact `LiveEntityHydrationController.AppearanceApplied` delegate; +- combat attack operations; +- camera-pointer gameplay frame; +- developer player-mode and command-bus targets; +- local teleport network sink; +- retained selection view-plane authority. + +The live-runtime component lifecycle remains attached through the Phase-6 +binding owner because it must outlive session teardown and stay callable until +`LiveEntityRuntime.Clear` completes. Landblock-loaded hydration may use that +same late lifetime when its publisher outlives the session result. + +### 4.3 Portal transfer + +The prepared tunnel follows the existing single-owner transaction: + +```text +Phase 6 fallback slot -> Phase 7 LocalPlayerTeleportController +``` + +If the destination factory throws, the fallback retains the tunnel. Once the +controller exists, Phase 7 immediately owns it for rollback. A later failure +disposes the controller and tunnel exactly once; the fallback is already empty. + +### 4.4 Streamer and session rollback + +The streamer is scope-owned before `Start`. Any later Phase-7 failure disposes +it, which joins the worker and releases pending work. The live-session +controller is also scope-owned immediately. Rollback order is: + +1. detach external bindings; +2. dispose local teleport if transfer completed; +3. dispose live-session ownership; +4. dispose the streamer; +5. aggregate and retain any incomplete cleanup for retry. + +Normal shutdown remains behaviorally ordered: quiesce input, gracefully retire +the live session and reset graph, withdraw frame borrowers, detach Phase-7 +bindings, stop the streamer, clear live entities, then release presentation and +GL owners. + +## 5. Publication and cutover + +- `OnLoad` calls one `SessionPlayerCompositionPhase.Compose(...)` paragraph. +- The old radius, streamer, session, hydration, player, and teleport + construction body is deleted. +- Phase 8 consumes `SessionPlayerResult`; it does not rediscover the new owners + through nullable window fields. +- Existing steady-state/reset code may temporarily read published fields until + Checkpoint I.8 completes the root cutover. +- No second GUID map, world state, input subscriber, portal owner, or session + authority is introduced. + +## 6. Automated gates + +### Construction and rollback + +- exact construction trace, including streamer-start and portal-transfer + positions; +- failure before and after streamer start stops the worker exactly once; +- failure at every bind/publication boundary releases in reverse order; +- partial cleanup retries only failed edges and never replays completed ones; +- portal destination-factory failure preserves fallback ownership; +- later failure disposes the transferred teleport owner exactly once; +- publication rejects replacement atomically. + +### Binding and lifetime + +- exact-owner unbind and stale-token rejection for every new deferred seam; +- `EntityReady` and `AppearanceApplied` detach the exact delegates once; +- callbacks are safe before bind and inert after deactivation where the source + contract permits it; +- live-runtime component teardown stays bound until live records are cleared; +- session/UI/command targets cannot retain a failed Phase-7 graph; +- runtime settings targets do not replay startup values when bound; +- no duplicate input, combat, streamer, hydration, or portal owner. + +### Behavior and structure + +- live/offline gates and initial placeholder origin remain unchanged; +- near/far and legacy radius selection are byte-for-byte equivalent; +- spawn-claim cell boundaries preserve the former memoized behavior; +- session packet routing, hydration order, combat target selection, player-mode + auto-entry, and portal presentation remain unchanged; +- `GameWindow` contains no Phase-7 construction body or spawn-claim algorithm; +- App Release tests, clean solution Release build, and full Release tests pass; +- source/divergence audit and three self-review passes are clean. + +## 7. Exit evidence + +I.7 is complete when Phase 7 is the production path, every Phase-7 external +edge has explicit reversible ownership, failure and retry gates pass, the old +window body is gone, documentation/memory report the measured class size and +test totals, and the commit is independently buildable. I.8 then composes the +update/render roots and terminal session start over the typed result graph.