diff --git a/docs/plans/2026-07-25-modern-runtime-slice-j.md b/docs/plans/2026-07-25-modern-runtime-slice-j.md index 1c277a04..00238ea3 100644 --- a/docs/plans/2026-07-25-modern-runtime-slice-j.md +++ b/docs/plans/2026-07-25-modern-runtime-slice-j.md @@ -354,7 +354,9 @@ graphical feel gates remain unchanged. ### J6 — world, portal, environment, and projection handshake -**Active 2026-07-26.** +**J6.0 active 2026-07-26.** Detailed owner inventory, retail ordering, +host-acknowledgement contract, execution ledger, and adversarial matrix: +[`2026-07-26-modern-runtime-slice-j6.md`](2026-07-26-modern-runtime-slice-j6.md). - Move authoritative teleport/session cell identity, world clock, weather state, and reveal-generation state required by gameplay. diff --git a/docs/plans/2026-07-26-modern-runtime-slice-j6.md b/docs/plans/2026-07-26-modern-runtime-slice-j6.md new file mode 100644 index 00000000..7f635861 --- /dev/null +++ b/docs/plans/2026-07-26-modern-runtime-slice-j6.md @@ -0,0 +1,311 @@ +# Modern runtime Slice J6 — world, transit, and host handshake + +**Status:** J6.0 ACTIVE +**Parent:** `2026-07-25-modern-runtime-slice-j.md`, J6 +**Authorization:** the user approved Slices F–L, including gameplay-owner +moves, on 2026-07-24 +**Purpose:** move the one authoritative world-environment and local-transit +lifetime into `AcDream.Runtime` while preserving the accepted retail portal +presentation and leaving graphical readiness, streaming, sky drawing, VFX, +audio, and UI in `AcDream.App`. + +## 1. Retail ordering oracle + +The load and placement boundary is fixed by the named retail client: + +- `SmartBox::TeleportPlayer @ 0x00453910` +- `SmartBox::UseTime @ 0x00455410` +- `gmSmartBoxUI::EndTeleportAnimation @ 0x004D65A0` +- `CPhysicsObj::enter_world @ 0x00516170` +- `SkyDesc::CalcPresentDayGroup @ 0x00500E10` +- `CPlayerSystem::Handle_Admin__Environs @ 0x0055DE20` + +The consolidated pseudocode is already captured in: + +- `docs/research/2026-07-15-retail-portal-space-pseudocode.md` +- `docs/research/2026-07-16-portal-completion-pseudocode.md` +- `docs/research/2026-07-24-retail-streaming-retirement-pseudocode.md` +- `docs/research/2026-04-23-daygroup-selection.md` + +The load-bearing order is: + +```text +fresh F751 notification + establish one teleport generation +matching accepted Position + establish one exact destination +CellManager finishes destination load + host acknowledges exact generation + destination readiness +SmartBox::TeleportPlayer / CPhysicsObj::enter_world + commit position and destination cell + resume destination simulation +gmSmartBoxUI::EndTeleportAnimation + continue private tunnel presentation +TunnelFadeOut -> WorldFadeIn + reveal normal world viewport +WorldFadeIn tail ends + send LoginComplete and complete the generation +``` + +The graphical host may delay the readiness acknowledgement until render, +composite-texture, and collision publication have converged. It does not own +the teleport generation, destination identity, materialization state, or +simulation availability. A headless host supplies the same acknowledgement +contract using its own required domains. + +## 2. Current owner inventory + +### 2.1 Authoritative state incorrectly retained in App + +| Current owner | State | J6 destination | +|---|---|---| +| `WorldEnvironmentController` | server-synced world clock, selected day group, weather, AdminEnvirons override, debug overrides | `RuntimeWorldEnvironmentState` | +| static `DerethDateTime.OriginOffsetTicks` | mutable Region calendar origin shared by every process session | instance `DerethCalendar` owned by each environment | +| `TeleportTransitCoordinator` | F751 freshness, Position correlation, accepted-destination history | `RuntimeWorldTransitState` | +| `WorldRevealLifecycleTelemetry` | reveal generation, destination, readiness, materialized/completed/cancelled/world-visible state | `RuntimeWorldTransitState` | +| `WorldGenerationAvailabilityState` | whether gameplay/world simulation may advance | borrowed projection of `RuntimeWorldTransitState` | +| `CurrentGameRuntimeViewAdapter.PortalView` | reconstructs Runtime portal state from App lifecycle state | direct borrowed Runtime view | + +### 2.2 App state that must remain App + +| Owner | Reason | +|---|---| +| `WorldRevealReadinessBarrier` | joins renderer, texture-upload, and collision-publication facts | +| `StreamingController` / destination reservation | graphical streaming and publication | +| `WorldRevealRenderResourceScheduler` | GPU upload priority | +| `PortalTunnelPresentation`, `TeleportAnimSequencer`, `TeleportViewPlaneController` | private graphical presentation | +| `WorldGenerationQuiescence` effects | clears graphical selection and suspends/resumes world audio | +| `LoadedSkyDesc` / `DayGroupData` projection | raw DAT-backed sky presentation and renderer input | +| terrain, EnvCell, sky, VFX, audio, UI owners | presentation | + +### 2.3 State that already has the correct Runtime owner + +- Current player full-cell and position: `RuntimeLocalPlayerMovementState`. +- Accepted entity position/timestamp state: `RuntimeEntityDirectory`. +- Canonical entity identity and incarnation: `RuntimeEntityObjectLifetime`. +- Physics placement/cell membership: `RuntimePhysicsState`. +- Network session generation and ordered transport: `LiveSessionController`. + +J6 must borrow these owners. It may not add a second current-cell field, entity +map, movement body, session generation, or packet queue. + +## 3. Target Runtime contracts + +### 3.1 Environment + +```csharp +public sealed class RuntimeWorldEnvironmentState +{ + WorldTimeService WorldTime { get; } + WeatherSystem Weather { get; } + RuntimeWorldEnvironmentSnapshot Snapshot { get; } + + void Initialize(RuntimeWorldEnvironmentDefinition definition); + void SynchronizeFromServer(double ticks); + RuntimeEnvironmentEffect ApplyAdminEnvirons(uint changeType); + void RefreshDayGroup(); + void ResetSession(); +} +``` + +The immutable definition contains only presentation-independent values: +calendar origin, sky tick rate, and ordered day-group descriptors with the +Core `SkyStateProvider`. Runtime owns the selected index and weather state. +App retains the raw `LoadedSkyDesc` and resolves Runtime's active index to the +matching `DayGroupData` for drawing. + +`WorldTimeService` receives an instance `DerethCalendar` and an injectable +`TimeProvider`; production no longer mutates process-global calendar origin or +reads wall time through a hidden static dependency. + +### 3.2 Transit/reveal + +```csharp +public readonly record struct RuntimeTeleportDestination(...); + +public readonly record struct RuntimeDestinationReadiness( + long Generation, + uint DestinationCell, + bool IsUnhydratable, + bool RenderReady, + bool CompositeReady, + bool CollisionReady); + +public sealed class RuntimeWorldTransitState : IRuntimePortalView +{ + bool QueueTeleportStart(ushort sequence); + RuntimeDestinationOfferResult OfferDestination(...); + bool ActivatePending(out RuntimeTeleportDestination destination); + + long BeginReveal(RuntimePortalKind kind, uint destinationCell); + bool AcknowledgeDestinationReadiness(in RuntimeDestinationReadiness ack); + bool AcknowledgeMaterialized(long generation, uint destinationCell); + bool AcknowledgeWorldViewportVisible(long generation); + bool Complete(long generation); + bool Cancel(long generation); + void ResetSession(); +} +``` + +All mutators validate the exact active generation and destination. A stale +acknowledgement cannot open a newer destination. Readiness is an immutable +host acknowledgement; Runtime owns the resulting lifecycle state. + +The snapshot separately exposes: + +- destination readiness; +- simulation availability; +- materialization; +- normal-world viewport observation; +- completion/cancellation. + +This preserves retail's two release edges: + +1. materialization resumes destination simulation; +2. the later tunnel/world swap releases graphical destination reservations. + +### 3.3 App adapters + +`WorldRevealCoordinator` becomes a graphical host adapter: + +- it asks Runtime to begin the generation; +- begins exact-generation streaming and render-resource reservations; +- evaluates App readiness and acknowledges the exact generation/cell; +- projects Runtime simulation-availability edges to selection/audio; +- releases graphical reservations only at the viewport edge; +- owns no lifecycle snapshot or generation counter. + +`LocalPlayerTeleportController` remains the portal presentation orchestrator. +It borrows `RuntimeWorldTransitState` for F751/Position correlation and +lifecycle facts, while retaining only translated render-space placement, +camera/view-plane state, tunnel animation, and App callback reentrancy guards. + +## 4. Execution ledger + +### J6.0 — owner proof and detailed plan + +- Re-read the named retail functions and existing consolidated pseudocode. +- Inventory every producer, consumer, reset edge, and checkpoint. +- Pin the target contracts, no-mirror rules, sub-slices, gates, and rollback + discipline in this document. + +Gate: documentation/source audit proves every mutable field has exactly one +planned owner and no accepted presentation edge changes. + +### J6.1 — instance-scoped environment owner + +- Add `DerethCalendar` and make `WorldTimeService` consume its exact instance. +- Add `RuntimeWorldEnvironmentState` and immutable environment definitions. +- Reduce App's `WorldEnvironmentController` to DAT conversion plus + `IWorldSceneSkyStateSource` projection. +- Route TimeSync, AdminEnvirons, diagnostics, render weather, and sky lookup + through the one Runtime state. +- Delete production mutation of `DerethDateTime.OriginOffsetTicks`. +- Add two-instance isolation, day-group equality, TimeSync, debug override, + AdminEnvirons, reset, and teardown tests. + +Gate: Core/Runtime/App focused tests, Release build, full tests, exact +day-group fixtures, and no Runtime dependency violation. + +### J6.2 — canonical reveal generation and typed readiness + +- Add `RuntimeWorldTransitState`, immutable readiness acknowledgement, and + direct `IRuntimePortalView`. +- Move lifecycle telemetry and generation state from App to Runtime. +- Make `WorldRevealCoordinator` a strict App host adapter. +- Replace App's mutable availability state with a read-only Runtime projection; + retain selection/audio side effects as exact edge observers. +- Reject stale generation, wrong destination, reordered, duplicate, and + post-cancel acknowledgements. +- Preserve unhydratable destination behavior and the five-second retail wait + cue without a timeout or forced reveal. + +Gate: login, portal, supersession, stale acknowledgement, callback failure, +session reset, and exact two-release-edge fixtures pass. + +### J6.3 — canonical F751/Position transit and placement handshake + +- Move `TeleportTransitCoordinator` state into the Runtime transit owner. +- Convert accepted network destination data once into + `RuntimeTeleportDestination`. +- Keep render-space translation/recenter and camera placement in App. +- Validate placement and materialization against the exact Runtime generation, + sequence, and destination cell. +- Derive current session cell from the existing Runtime movement/entity owner; + add no parallel current-cell field. +- Reset/cancel transit through Runtime's structural teardown. +- Delete the App transit coordinator and App portal-view reconstruction. + +Gate: Position-before-F751, F751-before-Position, duplicate/stale/wrapped +sequence, superseding teleport, same-landblock, cross-landblock, dungeon, +mid-portal reset, and reconnect traces match. + +### J6.4 — projection acknowledgement and owner cleanup + +- Make App presentation registration/withdrawal use typed generation-scoped + acknowledgements. +- Ensure simulation release, viewport reveal, reservation release, and final + completion each occur once and retain retryable suffixes after a callback + failure. +- Remove superseded App lifecycle/generation state and compatibility types. +- Extend normalized checkpoints and ownership ledgers with environment, + transit, readiness, and pending-host-ack counts. +- Add direct/no-window host fixtures proving Runtime can complete login, + portal, cancellation, and reset without loading App or a backend. + +Gate: source/dependency guards find no App authority or Runtime presentation +dependency; every failure-injection ledger converges to zero. + +### J6.5 — connected and documentation closeout + +- Run focused Core, Runtime, and App projects. +- Run `dotnet build AcDream.slnx -c Release`. +- Run the complete Release test suite. +- Rebuild the exact binary. +- Run fresh login, repeated recall/portal, world edge, dungeon, graceful + disconnect, reconnect, and mid-portal disconnect routes. +- Compare the accepted portal screenshots and presentation trace. +- Update architecture, code structure, milestone, roadmap, parent plan, + AGENTS/CLAUDE, divergence ledger, and durable memory. + +J6 is complete only when automated and connected evidence proves: + +- one Runtime environment owner; +- one Runtime transit/reveal owner; +- no stale destination acknowledgement can reveal a different generation; +- no App portal-state reconstruction remains; +- no portal timing, paperdoll, object-lifetime, VFX-tail, or world-void + regression; +- teardown and reconnect converge with no pending host acknowledgement. + +## 5. Mandatory adversarial matrix + +- two Runtime instances with different Region origins and server clocks; +- TimeSync while a debug override is active; +- day/year rollover and day-group reselection; +- every AdminEnvirons fog and sound value, plus unknown values; +- Position before F751 and F751 before Position; +- duplicate, old, equal, and `ushort`-wrapped teleport sequences; +- readiness for the wrong generation or destination; +- ready then superseded, materialized then cancelled, viewport ack before + readiness, and duplicate completion; +- destination recenter still pending; +- indoor render ready without EnvCell collision; +- outdoor collision ready without the full render neighborhood; +- unhydratable authoritative destination; +- callback reentrancy at begin, readiness, placement, viewport, and complete; +- disconnect during every portal animation state; +- same-process disconnect/reconnect and two simultaneous Runtime instances; +- graphical host withdrawal failure followed by retry; +- zero App/UI/Silk/OpenAL/Arch assemblies in direct Runtime tests. + +## 6. Commit and rollback discipline + +Each coherent production sub-slice lands separately after its focused, +Release, full-suite, dependency, and teardown gates. The exact production +commit and matching `git revert ` are recorded here, in the parent plan, +the closeout evidence, architecture, and durable memory before moving on. + +Documentation-only research/plan commits are not behavior rollback points. +No workaround, timer, forced-ready path, duplicated owner, or alternate +headless behavior is permitted.