Move camera pointer, framebuffer resize, and retained/devtools input edges behind focused reversible owners. Preserve input priority while making shutdown deactivate callbacks before live-session retirement and retry physical detach without stranding transport teardown.
155 lines
8.4 KiB
Markdown
155 lines
8.4 KiB
Markdown
# GameWindow decomposition — current truth
|
||
|
||
## Current state
|
||
|
||
The behavior-preserving App ownership campaign is complete through Slice 7 and
|
||
Slice 8 checkpoints A–E. `GameWindow.cs` moved from the 2026-07-21 baseline of
|
||
15,723 lines / 278 fields / 205 methods to 4,266 lines / 194 fields / 65
|
||
methods: 11,457 lines (72.9%) were removed without changing accepted gameplay
|
||
or rendering behavior.
|
||
|
||
| Slice | Ownership moved out | Closeout size |
|
||
|---|---|---:|
|
||
| 1 | world selection and interaction intent | 14,912 / 278 / 191 |
|
||
| 2 | live animation presentation | 14,546 / 277 / 190 |
|
||
| 3 | complete live-session lifecycle and routing | 14,310 / 274 / 190 |
|
||
| 4 | live-entity hydration, teardown, and network presentation | 10,301 / 267 / 163 |
|
||
| 5 | landblock build, publication, retirement, and shared-origin lifetime | 8,811 / 247 / 153 |
|
||
| 6 | complete update-frame orchestration | 7,026 / 241 / 108 |
|
||
| 7 | complete render-frame orchestration and failure recovery | 4,666 / 196 / 70 |
|
||
| 8 A–E | shell freeze, native/session/environment composition, reversible pointer/input/framebuffer ownership | 4,266 / 194 / 65 |
|
||
|
||
Slice 8 is an ordered checkpoint campaign rather than another feature-body
|
||
move. A froze/pruned the shell boundary; B gave all nine native window callback
|
||
edges one reversible owner plus host quiescence; C added `LiveSessionHost` for
|
||
reset/selection/entry/route composition while keeping `LiveSessionController`
|
||
the sole session owner. C also replaced the embedded ACE shortcut with the
|
||
named-retail `SkillFormula::Calculate @ 0x00591960` port. Partial route
|
||
construction and individual detach edges are retained and retried; reset and a
|
||
new generation cannot pass an incompletely detached route. D added
|
||
`WorldEnvironmentController` as the one-shot owner of WorldTime, loaded sky,
|
||
day-group selection, Weather, server synchronization, AdminEnvirons, and debug
|
||
cycles. `GameWindow` retains only ABI-compatible readonly aliases and typed
|
||
composition edges. The named-oracle correction is
|
||
`SkyDesc::CalcPresentDayGroup @ 0x00500E10`; the carried AdminEnvirons audio and
|
||
full fog/ambient/radar gaps are TS-54/TS-55.
|
||
|
||
E adds `CameraPointerInputController`, `FramebufferResizeController`, terminal
|
||
publish-before-attach Silk/dispatcher/retained input owners, and a quiescent
|
||
non-owning input-context view for optional devtools. Mouse-only hosts still
|
||
receive raw camera/cursor behavior. Logical callback deactivation runs before
|
||
the graceful session close; physical removal and the local mouse-look release
|
||
run only after session retirement. This prevents both copied callback reentry
|
||
and a failed event accessor from blocking F653/transport teardown. The carried
|
||
non-retail post-filter camera scalars are explicitly registered as TS-56.
|
||
|
||
Slice 6 implementation commits are `99a3e819`, `4e4aac2c`, `0bc9fda9`,
|
||
`c5570383`, `eeb0f6b4`, `947c61d2`, and production cutover `e91f3102`.
|
||
Slice 7 implementation commits are `7e4cfb37`, `733126a2`, `bc6f09f9`,
|
||
`6d6e5b5f`, `85239fb3`, `28e1cf80`, and production cutover `9d7df1bf`.
|
||
The detailed ledgers live under `docs/plans/2026-07-2*-gamewindow-slice-*.md` and
|
||
`docs/architecture/code-structure.md`.
|
||
|
||
## Frozen update graph
|
||
|
||
`GameWindow.OnUpdate` starts the profiler scope and calls one
|
||
`UpdateFrameOrchestrator.Tick`. The accepted production graph is:
|
||
|
||
1. retry retained live-entity teardown;
|
||
2. normalize/publish the update and PhysicsScript clocks;
|
||
3. converge streaming origin, residence, readiness, and rescued projections;
|
||
4. sample semantic input, raw mouse, and combat intent;
|
||
5. advance live objects and deferred presentation hooks;
|
||
6. drain inbound network traffic inside one world mutation batch;
|
||
7. run the local post-network position tail;
|
||
8. reconcile root/child/emitter/light presentation without advancing time;
|
||
9. expire liveness;
|
||
10. advance local teleport/reveal/tunnel presentation;
|
||
11. evaluate one-shot player-mode entry;
|
||
12. publish fly/chase/player camera presentation.
|
||
|
||
`LiveEntityRuntime` remains the canonical identity/incarnation owner.
|
||
`GpuWorldState` remains the spatial bucket owner. `LiveSessionController` owns
|
||
the session generation. Extracted phase owners query these typed runtimes and
|
||
must not create replacement dictionaries, service locators, or callback
|
||
facades into substantial `GameWindow` methods.
|
||
|
||
## Frozen render graph
|
||
|
||
`GameWindow.OnRender` creates one value-only `RenderFrameInput` and calls
|
||
`RenderFrameOrchestrator.Render`. The accepted healthy order is:
|
||
|
||
1. begin the GPU-flight transaction;
|
||
2. begin/reset frame resources, clear, and publish live resources;
|
||
3. begin the optional ImGui frame;
|
||
4. advance weather display preparation;
|
||
5. draw the complete world/PView/shared-alpha/particle/debug scene;
|
||
6. draw the portal/private viewport using the pre-private foundation snapshot;
|
||
7. refresh/draw paperdoll, retained gameplay UI, then submit ImGui;
|
||
8. capture a requested screenshot;
|
||
9. publish title/resource/frame diagnostics;
|
||
10. close the GPU-flight transaction.
|
||
|
||
Recovery is one reverse-lifetime transaction. An active ImGui frame closes
|
||
through the owning Silk controller, and text rendering restores exact borrowed
|
||
GL state on success or failure. The orchestrator and its immediate phase owners
|
||
retain no direct `GameWindow` or anonymous callback bag. Recursive reachability
|
||
through canonical UI/input owners is not frame ownership; the known paths and
|
||
review rule live in `docs/architecture/code-structure.md`.
|
||
|
||
## Accepted verification
|
||
|
||
- Slice 8 Checkpoint E Release suite: 7,477 passed / 5 fixture or environment
|
||
skips; App 3,108/3 skips, UI Abstractions 533/0, and all three independent
|
||
corrected-diff reviews are clean.
|
||
- Slice 8 Checkpoint D Release suite: 7,419 passed / 5 fixture or environment
|
||
skips; App 3,059/3 skips. Focused environment/boundary tests and all three
|
||
independent corrected-diff reviews are clean.
|
||
- Slice 8 Checkpoint C Release suite: 7,408 passed / 5 fixture or environment
|
||
skips; App 3,048/3 skips and Core.Net 548/0. All three independent corrected-
|
||
diff reviews are clean.
|
||
- Release suite: 7,341 passed / 5 fixture or environment skips.
|
||
- Connected lifecycle/reconnect: 315.6 seconds, graceful capped close and fresh
|
||
process uncapped reconnect passed; only 25 expected world-edge empty
|
||
landblocks.
|
||
- The six lifecycle PNGs preserve Slice 6 world geometry, depth, UI/paperdoll,
|
||
private viewport, and presentation. Differences are live weather/particles,
|
||
authoritative vitals, and small scripted camera settling.
|
||
- Synchronized nine-stop resource soak: 395.2 seconds, nine materializations,
|
||
all movement/jump/combat exercises, and graceful exit passed; update p95 was
|
||
at or below 0.8 ms. Caul return → plateau working/private delta was
|
||
+85.7/+59.3 MiB, inside the unchanged gate.
|
||
- Two immediately preceding identical-binary runs exceeded the coarse process-
|
||
residency threshold while deterministic ownership/lifecycle/timing checks
|
||
passed. #232 adds canonical resource-owner snapshots; do not solve this by
|
||
loosening the process-memory threshold or treating residency alone as an
|
||
identified owner leak.
|
||
- The 18–33 missing VFX table/emitter diagnostics are known DAT-driven records,
|
||
not a Slice 7 regression.
|
||
- TS-50, TS-51, and TS-53 remain registered; Slice 7 introduced no new retail
|
||
divergence.
|
||
|
||
## Next work
|
||
|
||
Slice 8 checkpoints F–L group the remaining action routing, settings, resource
|
||
ownership, startup, and shutdown wiring and reduce Silk callbacks to
|
||
narrow calls into input, update, render, resize, focus, and shutdown owners.
|
||
It removes leftover feature state only where Slices 1–7 already established a
|
||
canonical owner; it does not redesign gameplay, rendering, or resource lifetime.
|
||
The reviewed A–L execution ledger is
|
||
`docs/plans/2026-07-22-gamewindow-slice-8-composition-lifecycle.md`.
|
||
|
||
## Do not retry
|
||
|
||
- Do not reintroduce delegate facades into `GameWindow`; an ordering wrapper is
|
||
not an extraction until the state and behavior body move.
|
||
- Do not reorder the frozen update or render graphs during structural work.
|
||
TS-53 records the known retail host-order difference for a separate evidence-
|
||
backed port.
|
||
- Do not add a second GUID, session, spatial, or resource owner.
|
||
- Do not fold full `GameEntity` aggregation into this campaign; evaluate it
|
||
after Slice 8.
|
||
- Do not loosen the soak process-memory threshold to hide #232. Add canonical
|
||
owner snapshots and preserve process residency as a secondary guard.
|
||
- Small value/policy callbacks and diagnostics are acceptable only when they do
|
||
not call a substantial window body or hide mutable ownership.
|