docs(#145): Slice 3 — capture cellId/anchor-consistency + indoor-staleness edge cases + sweep threading map

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-21 11:08:13 +02:00
parent 9e184eb861
commit 865aae8876

View file

@ -322,6 +322,11 @@ Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"
Note: the OTHER `TryGetTerrainOrigin` site (`CellTransit.cs:484`, `BuildShadowCellSet`) is registration-side collision (Slice 4 concern), NOT the player pick — leave it for Slice 4.
**⚠ Edge cases surfaced during design (2026-06-21) — handle these or regress #98#112:**
- **cellId ↔ anchor must share a landblock.** The carried anchor `body.Position CellPosition.Frame.Origin` is the origin of `CellPosition`'s landblock; the pick's `AdjustToOutside` starts from the passed `cellId`. If `cellId` is the *lagging/marched* controller `CellId` while `CellPosition` is correct, the pick mixes a marched landblock with a correct local → garbage. **Fix: the controller passes `_body.CellPosition.ObjCellId` as the resolve cell for the OUTDOOR case** (so `cellId == CellPosition.ObjCellId`, consistent with the anchor); indoor keeps the BSP-tracked `CellId`. Selection: `(_body.CellPosition.ObjCellId outdoor & seeded && current is outdoor) ? CellPosition.ObjCellId : CellId`.
- **CellPosition goes stale indoors.** The Slice-2a setter only maintains `CellPosition` for outdoor cells (low word 1..0x40); while the player is inside a building (`CellId` indoor) it is NOT updated. On building EXIT (indoor→outdoor) the carried anchor would be stale. **Fix: re-seed `SnapToCell` from the resolve's outdoor result when membership transitions indoor→outdoor** (the resolve already returns the correct outdoor cell + the world position gives the local via the just-computed anchor). Verify with an indoor↔outdoor round-trip replay (CellarUp / cottage harness) in addition to the far-town test.
- **Sweep threading vehicle:** add `Vector3? CarriedBlockOrigin` to `SpherePath` (alongside `CheckCellId`, ~`:336`); set it in `PhysicsEngine.ResolveWithTransition` right after `InitPath` (`:975`) from `body`; read it at the `FindCellSet` call (`TransitionTypes.cs:2291`) and pass through `FindCellSet``FindCellList``BuildCellSetAndPickContaining` (default `null` = legacy `TryGetTerrainOrigin`, so every existing caller/test is unaffected).
**Files:**
- Modify: `src/AcDream.Core/Physics/CellTransit.cs:732-736` (the discarded-bool fallback), `:242` (`AddAllOutsideCells` block-origin subtraction), `:845-849` (containing pick), `:484` (the other seed)
- Modify: `src/AcDream.Core/Physics/PhysicsEngine.cs:603-625` (the resolve loop feeds the pick)