docs(runtime): close exact world host ownership
This commit is contained in:
parent
18d17d8bb1
commit
75f9510e10
13 changed files with 240 additions and 43 deletions
|
|
@ -241,7 +241,7 @@ src/
|
|||
World/
|
||||
RuntimeWorldEnvironmentState.cs -> canonical calendar/time/weather owner
|
||||
RuntimeWorldTransitState.cs -> canonical reveal generation/readiness owner
|
||||
-> J3–J5 and J6.1–J6.3 complete; J6.4 host acknowledgement active
|
||||
-> J3–J6 complete; J7 composition-root convergence active
|
||||
-> may reference Core, Core.Net, Content, and Plugin.Abstractions only
|
||||
-> must never reference App, UI, Silk.NET, OpenAL, Arch, or ImGui
|
||||
|
||||
|
|
@ -879,9 +879,16 @@ readiness may fall as resources transition without closing the accepted edge.
|
|||
|
||||
`WorldRevealCoordinator` is the graphical host adapter. It evaluates App's
|
||||
`WorldRevealReadinessBarrier`, acknowledges that typed result to Runtime, and
|
||||
owns only the streaming destination reservation, render-resource profile,
|
||||
selection/audio projection edges, and viewport release. App's former lifecycle
|
||||
telemetry/generation owner is deleted and
|
||||
owns only generation-scoped graphical resource receipts: the streaming
|
||||
destination reservation, render-resource profile, selection/audio projection
|
||||
edges, and viewport release. Runtime issues an exact
|
||||
`RuntimeWorldHostProjectionToken` for the reveal generation and destination
|
||||
cell, then retains the typed registration, simulation-release,
|
||||
reservation-release, and terminal acknowledgement suffix until App has
|
||||
actually projected it. Wrong-generation/cell acknowledgements cannot consume
|
||||
another reveal's work. Callback failure and re-entrancy preserve the exact
|
||||
remaining suffix instead of duplicating or leaking a reservation. App's former
|
||||
lifecycle telemetry/generation owner is deleted and
|
||||
`WorldGenerationAvailabilityState` is a read-only Runtime projection. While the
|
||||
normal world viewport is withheld, mesh and composite upload owners may admit
|
||||
more small destination items per frame, but retain the ordinary 8 MiB byte,
|
||||
|
|
@ -899,15 +906,15 @@ thread, never from the streaming worker. This is acdream's asynchronous equivale
|
|||
`SmartBox::UseTime` holding position completion while
|
||||
`CellManager::blocking_for_cells` is set.
|
||||
|
||||
`WorldRevealLifecycleTelemetry` is an observation seam owned by the
|
||||
coordinator, not a second lifecycle state machine. It records generation-scoped
|
||||
edges and rejects a normal-world viewport observed before canonical readiness.
|
||||
`WorldLifecycleAutomationController` consumes only coordinator snapshots plus
|
||||
resource counters; `FrameScreenshotController` performs the requested
|
||||
default-framebuffer readback after world and retained UI draw on the render
|
||||
thread. The external connected gate launches normal Release processes and
|
||||
observes these artifacts, but never mutates streaming, physics, GL, or entity
|
||||
state from a worker thread.
|
||||
`RuntimeStateCheckpoint` is the normalized observation seam. It records the
|
||||
canonical reveal snapshot plus environment and transit ownership ledgers; it is
|
||||
not a second lifecycle state machine. `WorldLifecycleAutomationController`
|
||||
consumes that borrowed Runtime checkpoint plus graphical resource counters and
|
||||
rejects a stable checkpoint while any host acknowledgement remains.
|
||||
`FrameScreenshotController` performs the requested default-framebuffer readback
|
||||
after world and retained UI draw on the render thread. The external connected
|
||||
gate launches normal Release processes and observes these artifacts, but never
|
||||
mutates streaming, physics, GL, or entity state from a worker thread.
|
||||
|
||||
### Teleport cell identity at the streaming boundary
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ src/AcDream.App/
|
|||
├── Streaming/
|
||||
│ ├── LandblockPresentationPipeline.cs # DAT build/apply/retire transaction and resource publication
|
||||
│ ├── StreamingController.cs # typed frame scheduler + reveal destination reservation
|
||||
│ ├── WorldRevealCoordinator.cs # canonical readiness, quiesce, and reservation lifetime
|
||||
│ ├── WorldRevealCoordinator.cs # graphical reveal projection and exact host receipts
|
||||
│ └── ... # shipped streamer/world-state owners
|
||||
├── Input/ # (already exists)
|
||||
├── Audio/ # (already exists)
|
||||
|
|
@ -472,14 +472,14 @@ useful ordering seam, but its ownership status is **partial**.
|
|||
| World environment | **J6.1 complete Runtime ownership** | `RuntimeWorldEnvironmentState` owns the instance-scoped Dereth calendar, synchronized clock, weather progression/state, selected day group, AdminEnvirons state, and typed debug overrides. App converts immutable DAT sky definitions once and projects the borrowed Runtime snapshot into rendering; no process-global Region origin or second App clock/weather owner remains (`902076c0`). TS-54/TS-55 register the remaining centered UI sound and full fog/ambient/radar behavior gaps. |
|
||||
| Live identity/lifetime | **J3 complete** | `RuntimeEntityObjectLifetime` owns the sole `RuntimeEntityDirectory`, live `ClientObjectTable`, direct views, and ordered entity/object stream. The directory owns canonical GUID/incarnation/local-ID identity, accepted snapshots/timestamps, parent state, operation versions, and tombstones. `LiveEntityProjectionStore` owns App graphical sidecars by exact `RuntimeEntityKey`; hydration, presentation components, `GpuWorldState` residence/visibility, and retryable teardown preserve that key without another authority. Exact receipts precede fallible callbacks, re-entrant commits drain synchronously in sequence, and stable reset/disposal must converge the complete ledger to zero (`f46ddb5c`, `420e5eea`, `e937cc36`, `5ef8b537`, `ce3ac310`, `119b7c11`). |
|
||||
| Inbound/object-frame order | **Complete App orchestration** | `UpdateFrameOrchestrator` owns the complete typed host phase graph; `RetailInboundEventDispatcher`, `RetailLiveFrameCoordinator`, `LiveObjectFrameController`, `LiveSpatialPresentationReconciler`, streaming/input/teleport/player-mode/camera owners preserve the accepted order. `GameWindow.OnUpdate` is one profiler-scoped handoff (`e91f3102`). |
|
||||
| World reveal/transit | **J6.3 complete Runtime ownership** | `RuntimeWorldTransitState` owns the sole monotonic login/portal reveal generation, wrap-safe F751 history, pending/active teleport sequence, both accepted F751/Position packet orders, exact destination, typed atomic readiness latch, generation/sequence/cell placement and materialization validation, simulation edge, viewport observation, completion, cancellation, retail wait cue, and portal count. `WorldRevealCoordinator` and `LocalPlayerTeleportController` are graphical host adapters over App readiness/reservations, render-space placement, tunnel, and UI; `WorldGenerationAvailabilityState` borrows Runtime truth and owns no mutable generation. The App transit coordinator and accepted-destination mirror are deleted (`a6860d55`, `acb845d8`, `6a063a27`). |
|
||||
| World reveal/transit | **J6 complete Runtime ownership** | `RuntimeWorldTransitState` owns the sole monotonic login/portal reveal generation, wrap-safe F751 history, pending/active teleport sequence, both accepted F751/Position packet orders, exact destination, typed atomic readiness latch, generation/sequence/cell placement and materialization validation, simulation edge, viewport observation, completion, cancellation, retail wait cue, portal count, and exact typed graphical-host acknowledgement suffix. `WorldRevealCoordinator` and `LocalPlayerTeleportController` are graphical adapters over App readiness, generation-scoped resource receipts, render-space placement, tunnel, and UI; failure/re-entrancy retains the exact unacknowledged suffix. `WorldGenerationAvailabilityState` borrows Runtime truth and owns no mutable generation. The App transit coordinator and accepted-destination mirror are deleted (`a6860d55`, `acb845d8`, `6a063a27`, `18d17d8b`). |
|
||||
| Retained gameplay UI | **Mostly complete feature ownership** | `RetailUiRuntime` and focused panel/controllers own layout and behavior. `GameWindow.OnLoad` still performs substantial service composition, which is allowed until the final composition cleanup. |
|
||||
| Action/combat/magic/movement | **J5 complete** | Runtime `RuntimeActionState` owns the exact selection, temporary target mode, interaction transactions, combat attack/target/mode, and spell-cast intent children. Interaction owns use/appraisal/pickup identity, ordered FIFO, and exact post-arrival token while borrowing J4's sole busy gate. `RuntimeLocalPlayerMovementState` owns the exact local controller, construction seam, autorun latch, typed view, and outbound MTS/jump/AP cadence. Retained bars, physical input, world/content queries, transport, lighting, toasts, drag/drop, effects, and animation remain App adapters/presentation. One combined Runtime ledger spans entity/object, gameplay, physics, remote, and projectile ownership (`b298f99f`, `f5f7b417`, `20df9d15`, `aa3f4a60`, `cdee7a4b`). |
|
||||
| Physics/remote simulation | **J5.5 complete** | `RuntimePhysicsState` owns one per-session engine, production cache/cell graph, transition scratch, shadow registry, typed collision admissions, canonical bodies/hosts/remotes, keyed ordinary/remote worksets, simulation, and cell commits. App streaming supplies immutable prepared collision; animation/shape adapters supply graphical inputs and project committed snapshots only (`7e6033d0`). |
|
||||
| Projectile simulation | **J5.6 complete** | `RuntimeEntityRecord`/`RuntimePhysicsState` own the canonical projectile component, exact-key workset, prediction/correction state, unchanged retail quantum/integration/sweep/collision loop, and cell commits. App resolves immutable Setup/DAT shape input and projects committed render, shadow, and effect-pose results only (`2aee3356`). |
|
||||
| Landblock presentation | **Complete** | `LandblockBuildFactory` owns the captured-origin DAT transaction; concrete render/physics/DAT-static publishers and `LandblockPresentationPipeline` own typed-meter publication and exact retryable retirement. `StreamingController` owns stable destination/control/unload/Near/Far queues and destination reservation. CPU mesh-cache restaging requires an exact live owner. `StreamingOriginRecenterCoordinator` serializes old-window retirement with teleport/session origin lifetimes. `GameWindow` retains construction and one pipeline field only (`c79d0a49`, closeout `4a205a3e`; Slice E closeout `91e82c3c`). |
|
||||
| Render-frame orchestration | **Complete** | `RenderFrameOrchestrator` owns the GPU-flight, resource, world/PView/shared-alpha, private-presentation, diagnostics, screenshot, and recovery graph. `GameWindow.OnRender` takes one logical window-size snapshot and performs one immutable handoff (`9d7df1bf`). |
|
||||
| Unified `GameEntity` | **Slice J active at J6.4** | Canonical identity, retained-object lifetime, direct views, ordered entity/object deltas, J4 gameplay state, and the complete J5 action/combat/magic/movement/physics/remote/projectile simulation graph share failure-safe Runtime owners while exact graphical sidecars stay in App. J5 closeout proves Runtime-only parity and one terminal ownership ledger. J6.1–J6.3 moved world environment, reveal-generation truth, and exact F751/Position destination correlation; J6.4 now closes typed graphical-host acknowledgements before J7 composes one `GameRuntime` root. |
|
||||
| Unified `GameEntity` | **Slice J active at J7** | Canonical identity, retained-object lifetime, direct views, ordered entity/object deltas, J4 gameplay state, and the complete J5 action/combat/magic/movement/physics/remote/projectile simulation graph share failure-safe Runtime owners while exact graphical sidecars stay in App. J5 closeout proves Runtime-only parity and one terminal ownership ledger. J6 moved world environment, reveal-generation truth, exact F751/Position destination correlation, and typed graphical-host acknowledgement into Runtime. J7 now composes those already-proven owners behind one `GameRuntime` root without adding another state layer. |
|
||||
|
||||
### 4.3 Revised extraction sequence
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ accepted-divergence entries (#96, #49, #50).
|
|||
|---|---|---|---|---|---|
|
||||
| AD-38 | Outgoing teleport viewports retire when retail's quantized animation level exceeds the last captured visible level 1022 (index 96), suppressing levels 1023/1024 up to 20.2 ms before retail's literal `elapsed >= 1.0` state edge. Incoming fades retain the exact timer. | `src/AcDream.Core/World/TeleportAnimSequencer.cs` (`OutgoingViewportReachedTerminalProjection`) | An uncapped 2000 FPS pass can publish the finite tunnel at levels 1023/1024 even though the paired 2013 retail capture switches viewports after 1022. The table-level cutover preserves the captured visible viewport ordering without throttling the application. | Exit sound, viewport replacement, and logout tunnel entry can occur at most two easing-table quanta (about 20.2 ms) earlier than retail's logical timer. | `UIGlobals::GetAnimLevel @ 0x004EE540`; `gmSmartBoxUI::UseTime @ 0x004D6E30`; paired retail/acdream captures documented in `docs/research/2026-07-15-retail-portal-space-pseudocode.md` |
|
||||
| AD-1 | Lost-cell machinery replaced by recoverable outdoor demote (**#107** safety net) + outdoor-restore `max(terrainZ, z)` under-terrain lift; retail goes `GotoLostCell` | `src/AcDream.Core/Physics/PhysicsEngine.cs:553` (+ :808) | acdream has no lost-cell state machine; outdoor landcell is the recoverable equivalent; the #107 auto-entry hold should make the demote branch unreachable | Gap in the hold → player committed to outdoor terrain inside/under a building (fake-grounded spawn, fall-through); a legit below-heightmap server restore is silently lifted — upward warp vs server | `GotoLostCell` pc:283418; `SetPositionInternal` 0x00515bd0, pc:283892-283945 |
|
||||
| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the required Near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud unhydratable-placement path. `WorldRevealCoordinator` owns this shared lifetime; diagnostic telemetry observes its generation without defining another readiness path. **Slice E3 refinement (2026-07-24):** the same generation now publishes an immediate `WorldGenerationQuiescence` edge: old-world drawing/spatial queries, simulation/effect clocks, reconciliation, targeting, and 3-D audio stop while retained physical teardown advances through metered cursors and destination network/UI/streaming/readiness remain live. **Slice E4 refinement (2026-07-24):** accepted render/physics/static publication may span update frames through retained exact cursors, but reveal still consumes only the completed spatial/render-ready generation; building and EnvCell snapshots remain invisible until complete and the final spatial identity swap stays observer-atomic. **Slice E5 refinement (2026-07-24):** the reveal generation owns one exact destination reservation across every typed budget dimension. Stale completion cannot consume or clear its replacement, and hydratable incomplete content is never force-revealed; portal transit retains the DAT tunnel and centered retail wait cue until readiness converges. The hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldGenerationQuiescence.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Streaming/StreamingOriginRecenterCoordinator.cs`; `src/AcDream.App/Streaming/LandblockPresentationPipeline.cs`; `src/AcDream.App/Streaming/StreamingController.cs`; `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; `src/AcDream.App/UI/PortalWaitNoticeController.cs`; `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal or continue simulating an old/partial collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, missing scenery, or a still-active old generation; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit remains in the authored tunnel and presents the centered wait cue after five seconds. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::UseTime` 0x004D6E30; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 |
|
||||
| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the required Near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud unhydratable-placement path. `RuntimeWorldTransitState` owns the shared reveal generation, accepted readiness, transit correlation, and exact generation/cell-scoped host-acknowledgement suffix. `WorldRevealCoordinator` is a graphical adapter holding only App resource receipts; normalized Runtime checkpoints observe ownership without defining another readiness path. **Slice E3 refinement (2026-07-24):** the same generation now publishes an immediate `WorldGenerationQuiescence` edge: old-world drawing/spatial queries, simulation/effect clocks, reconciliation, targeting, and 3-D audio stop while retained physical teardown advances through metered cursors and destination network/UI/streaming/readiness remain live. **Slice E4 refinement (2026-07-24):** accepted render/physics/static publication may span update frames through retained exact cursors, but reveal still consumes only the completed spatial/render-ready generation; building and EnvCell snapshots remain invisible until complete and the final spatial identity swap stays observer-atomic. **Slice E5 refinement (2026-07-24):** the reveal generation owns one exact destination reservation across every typed budget dimension. Stale completion cannot consume or clear its replacement, and hydratable incomplete content is never force-revealed; portal transit retains the DAT tunnel and centered retail wait cue until readiness converges. The hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.Runtime/World/RuntimeWorldTransitState.cs`; `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldGenerationQuiescence.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Streaming/StreamingOriginRecenterCoordinator.cs`; `src/AcDream.App/Streaming/LandblockPresentationPipeline.cs`; `src/AcDream.App/Streaming/StreamingController.cs`; `src/AcDream.App/Rendering/PortalTunnelPresentation.cs`; `src/AcDream.App/UI/PortalWaitNoticeController.cs`; `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal or continue simulating an old/partial collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, missing scenery, or a still-active old generation; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit remains in the authored tunnel and presents the centered wait cue after five seconds. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::UseTime` 0x004D6E30; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 |
|
||||
| AD-3 | Outdoor seeds always walk the transit array (retail skips the walk when the seed CLandCell is null/unloaded); per-cell lookups no-op on unhydrated data | `src/AcDream.Core/Physics/CellTransit.cs:503` | Equivalence argument: with nothing hydrated every lookup inside the walk no-ops, so the result matches retail's skipped walk | Near partially-streamed landblocks, building-transit promotion silently can't fire until structs hydrate — membership stays outdoor while the player is inside a building | `CObjCell::find_cell_list` 0052b535-0052b56c (null-CLandCell case) |
|
||||
| AD-4 | `point_in_cell` against an unhydrated CellBSP returns false (skip) rather than the null-node "inside" default; retail never queries unloaded cells | `src/AcDream.Core/Physics/CellTransit.cs:588` | The null-node default would make an unhydrated cell spuriously claim every point; skipping is the conservative streaming-safe choice | During hydration, a point genuinely inside a not-yet-loaded cell resolves outdoor/stale — transient membership misclassification driving wrong collision set and render root | `CEnvCell::find_visible_child_cell` :311397; cell-BSP vtable[0x84] |
|
||||
| AD-5 | Outdoor `point_in_cell` is an identity compare against the global XY-column cell from `LandDefs.AdjustToOutside` (no per-cell containment test) | `src/AcDream.Core/Physics/CellTransit.cs:865` | Landcells are disjoint 24 m columns — identity-compare against the column under the sphere centre is exactly equivalent to retail's per-candidate test | If block-origin/lcoord math is wrong at a landblock seam, the compare silently never matches — outdoor membership freezes at boundaries (the pre-#106 symptom) | `find_cell_list` pick pc:308788-308825; `CLandCell::point_in_cell` (get_block_offset pc:308804) |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue