docs(architecture): plan ordered GameWindow composition
This commit is contained in:
parent
c791f13853
commit
1d04b94da2
2 changed files with 316 additions and 1 deletions
|
|
@ -0,0 +1,314 @@
|
||||||
|
# GameWindow Slice 8 Checkpoint I — ordered production composition
|
||||||
|
|
||||||
|
**Status:** Active 2026-07-22.
|
||||||
|
**Parent:**
|
||||||
|
[`2026-07-22-gamewindow-slice-8-composition-lifecycle.md`](2026-07-22-gamewindow-slice-8-composition-lifecycle.md),
|
||||||
|
Checkpoint I.
|
||||||
|
**Integrated baseline:** `c791f138`; the reviewed Checkpoint-H tree plus the
|
||||||
|
complete-world-reveal history is merged. `GameWindow.cs` is 3,689 raw lines,
|
||||||
|
162 fields, and 37 methods. The Release build succeeds with the 17 warnings
|
||||||
|
tracked by #228 and all 7,606 tests pass / 5 intentionally skip.
|
||||||
|
**Behavior rule:** startup ownership and failure behavior may become explicit;
|
||||||
|
accepted input priority, settings, session/reset, update/render order, world
|
||||||
|
presentation, and retail gameplay behavior do not change.
|
||||||
|
|
||||||
|
## 1. Outcome
|
||||||
|
|
||||||
|
Replace the 2,149-line `GameWindow.OnLoad` body with one fixed production
|
||||||
|
composition pipeline. `GameWindow` remains the native host and write-only
|
||||||
|
publication shell. It does not become a service locator, and no extracted
|
||||||
|
phase stores or calls back into `GameWindow`.
|
||||||
|
|
||||||
|
The final startup shape is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GameWindow.OnLoad
|
||||||
|
-> GameWindowPlatformAcquisition.Acquire
|
||||||
|
-> GameWindowCompositionPipeline.Run
|
||||||
|
1 Host input / camera
|
||||||
|
2 Content / effects / audio
|
||||||
|
3 Settings / optional devtools
|
||||||
|
4 World / render resources
|
||||||
|
5 Interaction / retained UI
|
||||||
|
6 Live presentation / landblock publication
|
||||||
|
7 Streaming / session / local player / teleport
|
||||||
|
8 Atomic update + render roots
|
||||||
|
9 LiveSessionHost.Start, and nothing after it
|
||||||
|
```
|
||||||
|
|
||||||
|
Every phase consumes only the exact immutable prior results it needs and
|
||||||
|
returns a cohesive typed result. Results are borrowers. Newly acquired owners
|
||||||
|
move immediately into the existing lifetime slots, where shutdown remains the
|
||||||
|
sole release authority.
|
||||||
|
|
||||||
|
## 2. Fixed architecture
|
||||||
|
|
||||||
|
### 2.1 Platform prelude
|
||||||
|
|
||||||
|
`GameWindowPlatformAcquisition` is the exact production method used by
|
||||||
|
`OnLoad`. Its order is fixed:
|
||||||
|
|
||||||
|
1. create GL;
|
||||||
|
2. publish GL to the lifetime shell;
|
||||||
|
3. create the input context;
|
||||||
|
4. publish input;
|
||||||
|
5. return borrowed platform handles.
|
||||||
|
|
||||||
|
GL publication must happen before the input factory runs. An input-factory
|
||||||
|
failure leaves GL lifetime-owned for normal shutdown; local rollback never
|
||||||
|
double-disposes it. Viewport, diagnostics, camera, and GPU-frame resources are
|
||||||
|
not part of this narrow prelude.
|
||||||
|
|
||||||
|
### 2.2 Pipeline contract
|
||||||
|
|
||||||
|
Use nine explicit phase interfaces and immutable result records. The pipeline
|
||||||
|
holds no cumulative context and stores no final runtime graph. Locals pass only
|
||||||
|
the required sub-results forward.
|
||||||
|
|
||||||
|
Representative result grouping:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
HostInputCameraResult(InputGraph, CameraGraph, HostRenderGraph)
|
||||||
|
ContentEffectsAudioResult(ContentCatalogs, EffectsGraph, AudioGraph?)
|
||||||
|
SettingsDevToolsResult(ResolvedQuality, DevToolsGraph?)
|
||||||
|
WorldRenderResult(TerrainBuildContext, RenderFoundation)
|
||||||
|
InteractionUiResult(InteractionGraph, RetainedUiGraph?)
|
||||||
|
LivePresentationResult(LiveEntityGraph, WorldPresentationGraph)
|
||||||
|
SessionPlayerResult(StreamingGraph, SessionGraph, PlayerGraph, FrameParts)
|
||||||
|
FrameRootResult(LiveSessionHost)
|
||||||
|
SessionStartResult
|
||||||
|
```
|
||||||
|
|
||||||
|
Nested records are cohesive typed graphs, not dictionaries, `object` bags,
|
||||||
|
general service providers, or wrappers around the window.
|
||||||
|
|
||||||
|
### 2.3 Publication seam
|
||||||
|
|
||||||
|
`GameWindow` implements narrow write-only phase publishers. Publication methods
|
||||||
|
only validate single assignment and assign the existing shell fields. They do
|
||||||
|
not construct resources, invoke gameplay behavior, or provide runtime lookup.
|
||||||
|
The pipeline and phases release the publisher reference when `Run` returns.
|
||||||
|
|
||||||
|
Platform publication is narrower still so GL can publish before input
|
||||||
|
creation. Checkpoint J will move the exact shutdown manifest into the lifetime
|
||||||
|
owner; Checkpoint I does not duplicate or reorder that manifest.
|
||||||
|
|
||||||
|
### 2.4 Acquisition and rollback
|
||||||
|
|
||||||
|
Every concrete phase uses `CompositionAcquisitionScope` and named typed leases:
|
||||||
|
|
||||||
|
- unpublished acquisitions roll back in strict reverse dependency order;
|
||||||
|
- publication or transfer removes the resource from local rollback
|
||||||
|
immediately;
|
||||||
|
- lifetime-owned resources are never released locally;
|
||||||
|
- cleanup continues after an independent cleanup failure;
|
||||||
|
- the original construction failure and cleanup failures are retained;
|
||||||
|
- retry invokes only unfinished cleanup actions;
|
||||||
|
- successful cleanup never replays;
|
||||||
|
- duplicate publication and duplicate transfer are rejected.
|
||||||
|
|
||||||
|
This is not a generic shutdown bag. Long-lived owners remain in their focused
|
||||||
|
H-era slots and are retired in dependency order by the existing shutdown
|
||||||
|
transaction.
|
||||||
|
|
||||||
|
## 3. Frozen phase order and dependencies
|
||||||
|
|
||||||
|
### Phase 1 — host input and camera
|
||||||
|
|
||||||
|
Acquire viewport target, GPU-frame owner, world render diagnostics, keyboard
|
||||||
|
and mouse sources, input dispatcher, movement/camera bindings, mouse-look
|
||||||
|
cursor, orbit/fly camera, framebuffer camera target, and raw pointer owner.
|
||||||
|
|
||||||
|
Preserve:
|
||||||
|
|
||||||
|
- keyboard/mouse source attach before dispatcher attach;
|
||||||
|
- dispatcher attach before raw `MouseMove` attach;
|
||||||
|
- raw pointer attach before retained-UI device wiring;
|
||||||
|
- physical framebuffer size remains distinct from logical window size.
|
||||||
|
|
||||||
|
### Phase 2 — content, effects, and audio
|
||||||
|
|
||||||
|
Open the sole `DatCollection`; load magic, animation, collision, emitter,
|
||||||
|
particle, hook-frame, physics-script, lighting, and translucency owners. Audio
|
||||||
|
is optional, but failure can be swallowed only after its entire unpublished
|
||||||
|
prefix has converged cleanup. Hook-router registrations are reversible leases.
|
||||||
|
|
||||||
|
The physics-script advancement gate resolves the later entity-effect authority
|
||||||
|
through one typed deferred source; it must not capture the window or a null
|
||||||
|
snapshot.
|
||||||
|
|
||||||
|
### Phase 3 — settings and optional devtools
|
||||||
|
|
||||||
|
Apply the immutable startup settings snapshot after camera/audio exist and
|
||||||
|
before world/render/UI factories consume it. Compose optional devtools with a
|
||||||
|
transactional input/bootstrap/backend/framebuffer-target lease. Disabled
|
||||||
|
devtools acquire nothing. A devtools construction failure disables the feature
|
||||||
|
only after cleanup converges; cleanup failure fails startup rather than
|
||||||
|
stranding callbacks or native state.
|
||||||
|
|
||||||
|
Devtools live facts use focused sources for render diagnostics, canonical
|
||||||
|
world state, player mode, and player controller. No callback captures the host.
|
||||||
|
|
||||||
|
### Phase 4 — world and render resources
|
||||||
|
|
||||||
|
Load Region/environment/height/blend data, validate bindless support, then
|
||||||
|
construct terrain atlas, terrain shader, scene lighting, debug/text resources,
|
||||||
|
terrain renderer, WB mesh/render infrastructure, texture/sampler caches, and
|
||||||
|
the render foundation.
|
||||||
|
|
||||||
|
Required order includes bindless before atlas/terrain, and the final immutable
|
||||||
|
height/blend/surface build inputs are captured directly for worker use.
|
||||||
|
Constructor prefixes for debug lines, bitmap font, OpenGL graphics device,
|
||||||
|
particle batcher, global mesh buffers, portal depth, particles, samplers, and
|
||||||
|
terrain renderer must have a strong transactional guarantee.
|
||||||
|
|
||||||
|
### Phase 5 — interaction and retained UI
|
||||||
|
|
||||||
|
Compose combat target/attack, external-container and item interaction,
|
||||||
|
character/magic controllers, radar/chat/cursor assets, `UiHost`, and the
|
||||||
|
retained runtime lease. Retained bindings to later session, reveal, player,
|
||||||
|
diagnostic, and live-entity authorities use focused deferred sources. Host,
|
||||||
|
partial runtime, mounted runtime, and input bindings retain exact ownership.
|
||||||
|
|
||||||
|
### Phase 6 — live presentation and landblock publication
|
||||||
|
|
||||||
|
Compose WB/spawn adapters, canonical `GpuWorldState`, `LiveEntityRuntime`, live
|
||||||
|
motion/projectile/animation/effect/presentation owners, selection/paperdoll,
|
||||||
|
EnvCell/portal/sky/particle renderers, landblock publishers, and render
|
||||||
|
diagnostics. Bind the canonical live-runtime slot immediately after runtime
|
||||||
|
creation. Anonymous retained event handlers become named reversible bindings.
|
||||||
|
|
||||||
|
Portal tunnel ownership remains acquire -> prepare -> transfer. The fallback
|
||||||
|
slot and final controller never co-own the same resource.
|
||||||
|
|
||||||
|
### Phase 7 — streaming, session, local player, and teleport
|
||||||
|
|
||||||
|
Compose and publish the streamer before `Start`, then streaming/recenter/reveal,
|
||||||
|
session/hydration/network/liveness, player-mode/local-animation/shadow,
|
||||||
|
gameplay-input, commands, action-router, live-session host, and teleport
|
||||||
|
owners. All UI and devtool late sources bind here.
|
||||||
|
|
||||||
|
The current premature frame-root publication defect is removed: command
|
||||||
|
bindings and gameplay-action attachment complete in Phase 7, before Phase 8.
|
||||||
|
|
||||||
|
### Phase 8 — atomic frame roots
|
||||||
|
|
||||||
|
Construct all update/render leaves locally, then both roots, and publish the
|
||||||
|
pair once through `GameFrameGraphSlot` as the final phase action. A failure
|
||||||
|
before publication leaves the slot empty. A failure after publication leaves
|
||||||
|
the lifetime owner responsible for exactly one paired graph. No callback can
|
||||||
|
observe a half-pair.
|
||||||
|
|
||||||
|
### Phase 9 — terminal session start
|
||||||
|
|
||||||
|
Invoke only `LiveSessionHost.Start`. It is the absolute last startup operation.
|
||||||
|
There is no publication, callback attachment, command binding, or diagnostics
|
||||||
|
work afterward.
|
||||||
|
|
||||||
|
## 4. Focused live sources and reversible edges
|
||||||
|
|
||||||
|
Replace current host captures with focused authorities:
|
||||||
|
|
||||||
|
- `ILocalPlayerIdentitySource` for the server GUID;
|
||||||
|
- `ILocalPlayerModeSource` for player/fly state;
|
||||||
|
- a player-controller slot for current movement facts;
|
||||||
|
- `RenderRangeState` for near radius;
|
||||||
|
- `LiveWorldOriginState` for center coordinates;
|
||||||
|
- external-container state for current container;
|
||||||
|
- focused deferred session command/host authority;
|
||||||
|
- a canonical world-state source that cannot freeze the pre-runtime
|
||||||
|
placeholder;
|
||||||
|
- typed item/use/pick/selection/debug-fact operations;
|
||||||
|
- immutable phase-4 terrain worker inputs.
|
||||||
|
|
||||||
|
Add expected-owner unbind tokens for one-shot deferred composition slots that
|
||||||
|
can be bound before a later fallible edge. A failed phase must be disposable
|
||||||
|
and retryable without stale bindings or “already bound” failures.
|
||||||
|
|
||||||
|
Named reversible bindings replace anonymous subscriptions for projection
|
||||||
|
visibility, projection pose, entity-ready, appearance-applied, hook sinks, and
|
||||||
|
streamer start/stop.
|
||||||
|
|
||||||
|
## 5. Implementation checkpoints
|
||||||
|
|
||||||
|
1. **I.1 — contracts and executable oracle:** pipeline, platform prelude,
|
||||||
|
acquisition scope, fake phases, prefix/failure tests.
|
||||||
|
2. **I.2 — platform + Phase 1:** exact GL/input publication and host
|
||||||
|
input/camera cutover.
|
||||||
|
3. **I.3 — Phase 2:** content/effects/audio, reversible hooks, transactional
|
||||||
|
OpenAL construction.
|
||||||
|
4. **I.4 — Phase 3:** settings/devtools, complete optional rollback.
|
||||||
|
5. **I.5 — Phase 4:** world/render foundation and strong constructor
|
||||||
|
guarantees.
|
||||||
|
6. **I.6 — Phases 5–6:** retained UI, live presentation, landblock publishers,
|
||||||
|
typed late sources and event leases.
|
||||||
|
7. **I.7 — Phase 7:** streaming/session/player/teleport and all pre-frame
|
||||||
|
bindings.
|
||||||
|
8. **I.8 — Phases 8–9:** atomic roots, terminal start, delete old `OnLoad`
|
||||||
|
body, structural gates.
|
||||||
|
9. **I.9 — corrected-diff review, full gates, docs/memory, one bisectable
|
||||||
|
Checkpoint-I closeout commit.**
|
||||||
|
|
||||||
|
Small implementation commits may be used while the checkpoint is active, but
|
||||||
|
each must build and preserve production startup. The final I commit closes the
|
||||||
|
ledger only after the complete pipeline is live.
|
||||||
|
|
||||||
|
## 6. Automated acceptance
|
||||||
|
|
||||||
|
### Platform and pipeline
|
||||||
|
|
||||||
|
- Success trace is exactly `gl.factory -> gl.publish -> input.factory ->
|
||||||
|
input.publish`.
|
||||||
|
- GL-factory failure never calls input; input-factory failure retains GL in the
|
||||||
|
lifetime owner.
|
||||||
|
- Failure at each of nine phases runs exactly the preceding prefix and no
|
||||||
|
suffix.
|
||||||
|
- Every phase receives the exact immutable prior result instance.
|
||||||
|
- Success trace is phases 1–8 followed by terminal session start.
|
||||||
|
- Failure after frame publication withdraws the pair exactly once.
|
||||||
|
|
||||||
|
### Acquisition and concrete phases
|
||||||
|
|
||||||
|
- A/B/C prefix tests prove reverse rollback, transfer, aggregation, retry, and
|
||||||
|
no replay.
|
||||||
|
- Every concrete production phase has injected fault points at each
|
||||||
|
acquisition/attach/bind/publication edge.
|
||||||
|
- Optional audio/devtools continue only after successful rollback.
|
||||||
|
- Hook and event registrations unregister exactly once.
|
||||||
|
- Deferred slots unbind only the exact owner and reject stale release.
|
||||||
|
- Streamer start is reversed on later Phase-7 failure.
|
||||||
|
- Portal fallback/controller never co-own.
|
||||||
|
- Phase 8 never exposes one frame root without the other.
|
||||||
|
|
||||||
|
### Structural and repository gates
|
||||||
|
|
||||||
|
- `OnLoad` is a small platform/pipeline forwarder.
|
||||||
|
- No phase stores `GameWindow`, accepts a callback facade for substantial
|
||||||
|
host methods, or uses a service locator / `object` dictionary.
|
||||||
|
- `GameWindow` contains no construction body larger than one paragraph.
|
||||||
|
- `AcDream.Core` gains no App/GL dependency.
|
||||||
|
- App production build has zero warnings/errors; solution warnings remain only
|
||||||
|
the 17 tracked by #228.
|
||||||
|
- Focused tests, all App tests, and full Release suite pass.
|
||||||
|
- Connected lifecycle/reconnect and synchronized soak gates remain green when
|
||||||
|
the local ACE/visual environment is available.
|
||||||
|
|
||||||
|
## 7. Review gate
|
||||||
|
|
||||||
|
After the complete production cutover, run three independent read-only reviews:
|
||||||
|
|
||||||
|
1. retail/behavior-order conformance;
|
||||||
|
2. architecture, dependency direction, ownership, and shutdown symmetry;
|
||||||
|
3. adversarial failure, partial construction, reentrancy, and stale-binding
|
||||||
|
analysis.
|
||||||
|
|
||||||
|
Fix every confirmed finding at its root and repeat review until all three are
|
||||||
|
clean. No review finding is waived merely because the happy-path tests pass.
|
||||||
|
|
||||||
|
## 8. Documentation and commit exit
|
||||||
|
|
||||||
|
Checkpoint I closes only when the code-structure ledger, architecture, roadmap,
|
||||||
|
milestones, issues, `memory/project_gamewindow_decomposition.md`, `AGENTS.md`,
|
||||||
|
and `CLAUDE.md` agree on the same production pipeline and measured class size.
|
||||||
|
No retail-divergence row is added for a behavior-preserving ownership move; any
|
||||||
|
discovered behavioral adaptation is recorded in the same commit that keeps it.
|
||||||
|
|
@ -29,7 +29,8 @@ audit.
|
||||||
- [x] H — give terrain atlas, sky shader, retained `UiHost`, and both frame roots
|
- [x] H — give terrain atlas, sky shader, retained `UiHost`, and both frame roots
|
||||||
explicit single ownership and transfer seams.
|
explicit single ownership and transfer seams.
|
||||||
- [ ] I — group `OnLoad` into small ordered, fakeable composition phases with
|
- [ ] I — group `OnLoad` into small ordered, fakeable composition phases with
|
||||||
transactional partial-acquisition rollback.
|
transactional partial-acquisition rollback. Active detailed plan:
|
||||||
|
[`2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md`](2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md).
|
||||||
- [ ] J — move the exact retryable shutdown manifest to a focused lifetime
|
- [ ] J — move the exact retryable shutdown manifest to a focused lifetime
|
||||||
owner and prove all partial-load/reentrant/retry paths.
|
owner and prove all partial-load/reentrant/retry paths.
|
||||||
- [ ] K — in a separate #232 commit, add canonical owner snapshots to every soak
|
- [ ] K — in a separate #232 commit, add canonical owner snapshots to every soak
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue