diff --git a/docs/research/2026-06-24-teleport-out-issues-handoff.md b/docs/research/2026-06-24-teleport-out-issues-handoff.md new file mode 100644 index 00000000..c202f64a --- /dev/null +++ b/docs/research/2026-06-24-teleport-out-issues-handoff.md @@ -0,0 +1,96 @@ +# Handoff — two teleport-OUT issues (no-collision-after-death, char-missing-after-portal) — 2026-06-24 + +**Branch/worktree:** observed on `claude/thirsty-goldberg-51bb9b` +(`C:\Users\erikn\source\repos\acdream\.claude\worktrees\thirsty-goldberg-51bb9b`). +References / named-retail live in the MAIN repo `C:\Users\erikn\source\repos\acdream\`. + +> **These are NOT regressions from the dense-town FPS work.** That work (commits +> `290e731` cell-object batching, `9f51a4d` cell-particle consolidation, `a9d06a6` +> apparatus strip, `02578dd` docs) is **finalized + committed** and touched +> **render files ONLY** — zero physics / collision / streaming / movement / +> membership code (verified: `git show --name-only 290e731 9f51a4d a9d06a6`). Do +> NOT suspect those commits. The only indirect link: higher FPS makes the same +> few-tick transient render across more frames, so it's more *noticeable*; the +> underlying bug predates the FPS work (and collision is FPS-independent — physics +> ticks at a fixed rate). + +--- + +## The two issues (user-observed, 2026-06-24) + +Both are on the **teleport-OUT-to-outdoor** path and are almost certainly the same +known **placed-but-unstreamed streaming gap** (#135/#138 family). ISSUES §51 says a +streaming-gap fix "would fix **both** symptoms." They're split into two prompts only +so they can be tackled independently — whoever picks one should read both. + +### Issue A — no collision after death → portaled to Holtburg +- **Symptom:** after dying and being teleported to Holtburg, the player has **no + collision** (falls through / clips). +- **Root (known, NOT this session's work):** the *placed-but-unstreamed gap* — on a + teleport the player is placed immediately, but the destination landblock streams + in a few ticks later; during that gap the physics resolve runs against an **empty + world** (no terrain/collision meshes loaded), so collision finds nothing. +- **ISSUES refs:** [`docs/ISSUES.md:51`](../ISSUES.md) (the far-town runaway/march + + Z free-fall, "same root as #135/#138 placed-but-unstreamed gap"), and + [`docs/ISSUES.md:138`](../ISSUES.md) (acceptance: "the outdoor world fully + streamed, **collision working**"). Whether the death lands in a dungeon-exit + (#138 proper) or an outdoor respawn-to-lifestone, the placement→stream→resolve + timing is the same. + +### Issue B — char missing sometimes after portal to outside +- **Symptom:** after portaling outside, the **character (and other entities) are + missing for a moment**, then pop in. +- **Root (known = #138):** teleport-OUT re-hydrates world entities with **fresh + monotonic Ids** a few ticks after arrival (`GameWindow` ~`:3251`, + `Id = _liveEntityIdCounter++`); during that gap they aren't in the draw set, so + they appear late ("objects come back"). The player is one of them. +- **ISSUES refs:** [`docs/ISSUES.md:265`](../ISSUES.md) (#138 — "Teleport OUT of a + dungeon loads the outdoor world incompletely + position desync"), + [`docs/ISSUES.md:299`](../ISSUES.md) (the fresh-Id re-hydration detail + the + cache-invalidation side-finding). + +--- + +## ⚠ This is the DELICATE area — read before touching + +1. **DO NOT guess-patch.** The teleport/streaming runaway burned **~5 failed + attempts** (#145). Build the apparatus FIRST (capture → replay), per + `memory/feedback_apparatus_for_physics_bugs.md`. +2. **A "streaming HOLD" was tried and REVERTED.** Freezing the per-tick resolve + until the landblock loads produced a ~10 s freeze; the user called it "shaky and + bandaid" (`feedback_no_holds_for_slow_foundation` in memory). The real fix is + **fix the foundation** — make the destination stream *with* placement (the async + equivalent of retail's synchronous load), not a gate that masks a slow stream. +3. **Capture first.** Reproduce a real teleport and capture the + placement→stream→resolve sequence before proposing anything. + +## Where to start reading (in order) +- `claude-memory/project_physics_collision_digest.md` — physics / collision / + cell-membership SSOT + the DO-NOT-RETRY table. **START HERE.** +- `docs/ISSUES.md` #135, #138, #107, #145 (the teleport/streaming family). +- `memory/reference_two_tier_streaming.md` — the A.5 streaming architecture + (Region → Controller → LandblockStreamer → GpuWorldState; near/far radii). +- The teleport/placement + streaming code: grep `GameWindow` for the snap/placement + path (`[snap]`, `EXIT-expand`, `_liveEntityIdCounter`), the streaming + `dungeon EXIT-expand → (x,y)` logs, and `PlayerMovementController` / `PhysicsEngine` + arrival resolve. + +## Capture apparatus (already in the tree) +- `ACDREAM_CAPTURE_RESOLVE=` — JSON-Lines of every player-side + `PhysicsEngine.ResolveWithTransition` (inputs + body before/after + result). + Run it across a death→Holtburg teleport to see the resolve running against the + empty world during the gap. +- `ACDREAM_PROBE_CELL=1` — one `[cell-transit]` line per player cell change + (old→new, reason). Low volume; shows the post-teleport cell march. +- `ACDREAM_PROBE_RESOLVE=1` — per-resolve line (input/target/output, grounded, + contact-plane, responsible entity). Heavy. +- Launch (PowerShell): user `notan` / `MittSnus81!`, local ACE `127.0.0.1:9000`. + See CLAUDE.md "Running the client against the live server". + +## Likely fix shape (hypothesis, NOT confirmed — capture first) +Make the teleport destination's near landblocks **stream synchronously (or +placement waits on the first stream tick)** so the arrival resolve never runs +against an empty world, AND the entity re-hydration completes before/with the first +drawn frame — rather than a per-tick HOLD. Both symptoms (no-collision, char-missing) +collapse to "the world isn't there yet when we place + resolve + draw." Confirm the +exact gap timing from a capture before committing to a shape.