diff --git a/docs/ISSUES.md b/docs/ISSUES.md index a41d2a48..98207867 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -80,6 +80,36 @@ What does NOT go here: 1` (a 3x3 landblock neighborhood), while the normal configured view extends substantially farther; this permits the world viewport to open before its visible static destination is complete. +- **#281 — DONE (2026-08-03) — the stabilization commits left the automated + suites red, and the world-frame contract they introduced had no coverage.** + The 2026-08-03 handoff recorded "six selected fixture failures". A measured + baseline found **43**: the App suite was fully green at `01f4791e` and + `670f307c` broke 28 tests in one commit (`f24532ad` added 2 more), while the + Runtime suite lost 13 — 12 of them in `RuntimeRemoteFirstEntryStateTests`, + the exact conductor `670f307c` gated. Both commits were gated on focused + runs only. Root cause A (`670f307c`): remote first-entry placement now + resolves its landblock-local Create origin through Runtime's world frame + (`RuntimeSetPositionState.PrepareMover`) and returns + `RetrySetupUnavailable` until that frame exists, and ONLY the accepted + local-player Create publishes it + (`RuntimeEntityObjectLifetime.RegisterEntityCore` -> + `RuntimePhysicsState.ObserveLocalWorldFrame`). Fixtures that drove remote + conductors in a player-less world — a state production never occupies — + parked forever, so residences never retired. The production gate is correct + and matches App's own `LiveWorldOriginState` (initialized from the player + spawn; `Recenter` called only from + `StreamingOriginRecenterCoordinator.Advance` at a teleport boundary), so the + fixtures were stale, not the assertions: every one was repaired by supplying + the missing precondition without altering a single expected value. Root + cause B (`f24532ad`): `EffectCellId` is now populated at materialization and + wins over `ParentCellId` in `EntityEffectPoseRegistry.UpdateRoot`, and + projectile classification reads the canonical body's own + `CellPosition.ObjCellId` instead of deriving it from the sidecar. Two + rendering fixtures still modelled the pre-change shape. New + `RuntimeWorldFrameTests` pins the previously untested contract, including + the load-bearing rule that ordinary movement across a landblock boundary + must NOT rebase the frame while an accepted teleport must. Complete Release + solution: 10,831 passed / 4 skipped / 0 failed. **Retail oracle:** `CellManager::PreFetchCells @ 0x00455820` sets `blocking_for_cells` until `LScape::PreFetchCells @ 0x00505660` has walked diff --git a/tests/AcDream.App.Tests/Rendering/LiveEntityAnimationSchedulerTests.cs b/tests/AcDream.App.Tests/Rendering/LiveEntityAnimationSchedulerTests.cs index ce362c03..5b311aa9 100644 --- a/tests/AcDream.App.Tests/Rendering/LiveEntityAnimationSchedulerTests.cs +++ b/tests/AcDream.App.Tests/Rendering/LiveEntityAnimationSchedulerTests.cs @@ -305,8 +305,20 @@ public sealed class LiveEntityAnimationSchedulerTests CellId = Cell, Airborne = false, }; - remote.Body.Position = animation.Entity.Position; remote.Body.Orientation = animation.Entity.Rotation; + // f24532ad: projectile classification now reads the canonical body's + // own cell frame (ProjectileController:184-190 — + // body.CellPosition.ObjCellId / .Frame.Origin) instead of deriving it + // from the sidecar's FullCellId and the streaming center, because a + // residence-managed Create legitimately still has FullCellId 0. A + // Runtime-committed body therefore always carries its (cell, local) + // frame; seed this shared body through the same placement API rather + // than assigning Position alone, which would leave it cell-less and + // be correctly refused. + remote.Body.SnapToCell( + Cell, + animation.Entity.Position, + animation.Entity.Position); remote.Body.State = ProjectileState; remote.Body.InWorld = true; remote.Body.TransientState = TransientStateFlags.Active diff --git a/tests/AcDream.App.Tests/Rendering/Vfx/LiveEntityLightControllerTests.cs b/tests/AcDream.App.Tests/Rendering/Vfx/LiveEntityLightControllerTests.cs index 298bc97d..dbbff468 100644 --- a/tests/AcDream.App.Tests/Rendering/Vfx/LiveEntityLightControllerTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Vfx/LiveEntityLightControllerTests.cs @@ -22,7 +22,15 @@ public sealed class LiveEntityLightControllerTests LightSource light = Assert.Single(fixture.Sink.GetOwnedLights(entity.Id)!); entity.SetPosition(new Vector3(20, 30, 40)); + // f24532ad: a canonical cell move now writes BOTH sidecar cells + // together (LiveEntityRuntime.RebucketLiveEntity:845-856), because + // retail's CPhysicsObj::set_cell changes the one CObjCell that + // ShouldDrawParticles reads. EntityEffectPoseRegistry.UpdateRoot:163 + // resolves EffectCellId ?? ParentCellId, so moving the entity by + // ParentCellId alone would leave effects and lights on the stale + // materialization cell. entity.ParentCellId = 0x01010002u; + entity.EffectCellId = 0x01010002u; Assert.True(fixture.Poses.UpdateRoot(entity)); fixture.Controller.Refresh();