docs(#145): verified root cause + decision to port cell-relative physics frame (Option B) + handoff
Workflow wf_87607d15-c43 (4 research streams + synthesis + 3 adversarial verifiers, HIGH confidence) confirmed the far-town runaway is a cell-membership label cascade from a discarded TryGetTerrainOrigin bool (CellTransit.cs:736 -> (0,0) origin for unstreamed neighbors), not a free-fall; 17410 is a wire artifact. User chose the architectural fix: port retail's cell-relative Position + retire _liveCenter from physics. Handoff doc carries the verified mechanism, the retail port table (decomp addresses), acdream divergence sites, apparatus (desync-capture.jsonl + probes + harness template), and the brainstorming-gate requirement. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a4f0b51894
commit
67f98e8e72
2 changed files with 244 additions and 5 deletions
|
|
@ -71,11 +71,52 @@ Holtburg↔dungeon works because Holtburg is the startup center; the far town ex
|
|||
412/498/710); it did NOT fire for the far town during the runaway (746+) — and it only adds RENDER
|
||||
entities, never the physics `_landblocks` the resolver iterates.
|
||||
**Apparatus:** `[cell-transit]` trail (`ACDREAM_PROBE_CELL=1`) + `desync-capture.jsonl` (72,401
|
||||
`ResolveWithTransition` frames, `ACDREAM_CAPTURE_RESOLVE`). Suspected: the per-frame outdoor resolve
|
||||
(`PhysicsEngine.Resolve` / `AdjustPosition` iterating `_landblocks`) does not normalize the local
|
||||
position across a landblock crossing the way retail's `set_position`/`change_cell`/`AdjustPosition`
|
||||
does — port that. Research workflow running (acdream resolver code + retail named-decomp/Ghidra
|
||||
oracle + capture characterization → synthesis → adversarial verify).
|
||||
`ResolveWithTransition` frames, `ACDREAM_CAPTURE_RESOLVE`). **ROOT CAUSE — VERIFIED 2026-06-21 (multi-agent workflow + adversarial verification, decomp-confirmed against live Ghidra):**
|
||||
It is a **cell-membership cascade**, NOT a real free-fall. The physics body stays small + correct
|
||||
(capture: max|Y|≈86 m, settles at the true rest `(-6.1,-30.2,12.0)`); only the **cell id** marches
|
||||
one landblock south per physics quantum (~33 ms) until the landblock-Y byte underflows to 0x00. The
|
||||
`17410` is a **wire-conversion artifact** (the outbound `localY = Position.Y − (lbY−_liveCenterY)·192`
|
||||
adds back 91×192 once `lbY` marched to 0), never a physics value.
|
||||
**The bug (single source line):** `CellTransit.cs:736` —
|
||||
`cache.CellGraph.TryGetTerrainOrigin(currentCellId, out var blockOrigin)` **discards the bool**.
|
||||
For a far town, the player is placed at the southern landblock edge (world-Y≈0.3) with **stale
|
||||
southward running velocity** (teleport doesn't idle the motion state); the first tick crosses Y=0
|
||||
into landblock `0xC95A`, which **has not streamed in yet** → `TryGetTerrainOrigin` returns `false`
|
||||
with `origin=Vector3.Zero` (the comment at `CellTransit.cs:732-735` self-documents this "legacy
|
||||
anchor-frame" fallback). `(0,0)` is handed to `AddAllOutsideCells` (`:758`) → `GetOutsideLcoord`
|
||||
(`LandDefs.cs:110-111`) does `ly += floor(worldY/24)` = `floor(-0.088/24) = -1` → cell marches one
|
||||
block south. The correct origin `(0,-192)` would give `floor(191.9/24)=+7` (right region) — the
|
||||
missing −192 rebase IS the bug. Every subsequent neighbor is also unstreamed → the cascade
|
||||
self-perpetuates 91 times. **Far-town-only** because Holtburg (the streaming startup center) has all
|
||||
neighbors permanently registered, so the fallback never fires + spawns are mid-block (no Y=0 cross).
|
||||
**Retail contrast (decomp-confirmed, addresses re-verified in Ghidra patchmem):** retail stores
|
||||
position CELL-RELATIVE (`Position{ uint objcell_id; Frame{ m_fOrigin ∈ [0,192) } }`, `acclient.h:30659`)
|
||||
and rebases the ACTUAL stored origin in place on every placement via `Position::adjust_to_outside`
|
||||
(0x00504A40) → `LandDefs::adjust_to_outside` (0x005A9BC0, wraps origin into [0,192) + recomputes the
|
||||
cell id) called from `AdjustPosition` (0x00511D80) / `SetPositionInternal` (0x00515BD0); cross-cell
|
||||
offsets come only from `get_block_offset` (0x0043E630, delta of two cell ids, zero within a
|
||||
landblock). An inconsistent (cell, local) pair is structurally impossible in retail. acdream's
|
||||
streaming-relative physics frame (`worldXY=(lb−_liveCenter)·192+local`, per-landblock baked
|
||||
WorldOffset) is the deeper divergence; the proximate bug is the discarded-bool `(0,0)` fallback.
|
||||
|
||||
**FIX DIRECTION (report-only — awaiting user approval):**
|
||||
- **4a (targeted, faithful, this-session):** honor `TryGetTerrainOrigin`'s `false` at `CellTransit.cs:736`
|
||||
— when the current landblock's terrain isn't resident, the outdoor pick has no trustworthy
|
||||
block-local frame, so HOLD the current (cell, position) verbatim (no march), the same
|
||||
"frame-not-yet-authoritative ⇒ return input" contract the NO-LANDBLOCK Resolve branch already uses.
|
||||
PAIR with **idle the motion state on teleport arrival** (stop re-applying the dungeon running
|
||||
velocity the same frame as `SetPosition`) so the body never attempts the first crossing before
|
||||
terrain streams. Adaptation (not a direct retail port — retail gets it free via cell-relative
|
||||
storage) ⇒ needs a divergence-register row. Deterministic replay test from the capture
|
||||
(`TeleportFarTownRunawayTests`: with `0xC95A` unregistered, resolve returns `currentCellId`
|
||||
unchanged). Consumer sites to cover via the early-return: `:758/242` (seed), `:845` (pick), `:484`.
|
||||
- **4b (architectural, file as a phase, brainstorm-gated):** port retail's cell-relative physics
|
||||
`Position` + make `_liveCenter` render-only + `get_block_offset` as the only cross-cell translation.
|
||||
Removes the whole class structurally. Multi-commit.
|
||||
**Open items:** map-edge wedge (verbatim-hold could hover the player at a boundary if the needed
|
||||
neighbor never streams — likely mitigated by the motion-idle + the destination center always
|
||||
streaming; verify). **Confidence: HIGH** (all 3 adversarial lenses holdsUp=true; capture- and
|
||||
decomp-verified). Full report: workflow `wf_87607d15-c43`.
|
||||
|
||||
**[ORIGINAL #145 — source-frame overlap, FIXED 2026-06-20; history below]**
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue