6.6 KiB
Handoff — teleport issues cluster (2026-06-21)
Branch: claude/thirsty-goldberg-51bb9b — committed, NOT merged ("merge later").
Account: notan / MittSnus81! → +Je. Portal via the Town Network hub (0x0007) to far towns.
What shipped this session (context)
#145 cell-relative physics frame (Option B), Slices 1–3 + 7 (438bb68→403a338). The carried-anchor
fix closes the far-town cascade for a STREAMED-terrain arrival — live-verified across ~10 far-town
landblocks over 2 sessions, zero march. Design + plan:
docs/superpowers/specs/2026-06-21-145-cell-relative-physics-frame-design.md + the matching plan.
Adversarial review passed (2 flagged issues were verified false positives). Slices 4–6 (contact-plane /
walkable cell-relative + _liveCenter fully render-only — invisible architectural completeness) remain.
Work item A — #145 RESIDUAL (reopened): unstreamed-arrival-near-edge cascade
Trigger: a teleport that arrives onto a NOT-YET-STREAMED landblock near an edge → the cascade
recurs (+ a Z free-fall). Evidence (launch5.log):
[snap] claim=0xC98C0028 pos=(113.666,190.259,22.010) branch=NO-LANDBLOCK (lbs=0) -> verbatim— arrival local Y=190.3, 1.7 m from the 192 edge, destination not streamed → cell marches0xC98C → 0xC9FE(+2 lbY/tick), Z free-falls 22→−19; outbound wire sends the marched cellC9FE0031+ compensating garbagelocalY=−21684→ ACEMOVEMENT SPEED/failed transition→ player stuck.- Same session, mid-block unstreamed arrival
0x977B000C(Y=73.8) → Z free-fall only, no march. - Hub
0x00070133VALIDATED (cells resident) → fine.
Root (HYPOTHESIS — not apparatus-confirmed): outdoor teleport places immediately but the destination
streams a few ticks later (streaming: dungeon EXIT-expand -> (201,140) logs just after placement). During
the gap the resolve runs against an empty world; at an edge the player crosses into the unstreamed
neighbour, where the carried anchor (which computes to (0,0,0) at the recentered center) gives no
protection. Same root as the Z free-fall (#135/#138 placed-before-streamed gap).
⚠️ DO NOT guess-patch (original #145 burned 5 attempts). Apparatus first: add a diagnostic that logs
the anchor value + the engagement-guard state in PhysicsEngine.ResolveWithTransition at the crossing
tick (behind a probe flag), reproduce a 0xC98C-style arrival once, and confirm whether the anchor
disengages (CellId/CellPosition landblock divergence) or the body is repositioned into a marched frame
first. Then the fix is a known quantity.
Likely fix: a streaming-gap HOLD — freeze the per-tick resolve (no integration/gravity, no membership march) while the player's landblock is unloaded, until it streams in (a few ticks). The async-streaming equivalent of retail's synchronous load; would fix both the cascade and the Z plunge. Note: this may be subsumed by Work item B — the retail teleport flow holds until the world loads, so there's no unstreamed gap to begin with. Decide A-vs-B ordering at brainstorm.
Work item B — KEYSTONE FEATURE: the retail teleport flow
Symptoms (user-reported; all ONE root):
- Camera floats to the destination on teleport (disliked).
- Teleport takes too long / feels off vs retail.
- Player input is not locked during teleport.
Retail behaviour (user = oracle, treat as axiom): teleport plays an animation (portal effect), holds input + camera, waits for the world to load, then exits/places the player. Used for ALL teleportation: login, logout, death, portal.
Insight: acdream places immediately (raw placement → the floating camera + the unstreamed gap). A faithful retail teleport flow (anim + input/camera lock + hold-until-loaded + single exit point) fixes the float, the timing, the input-lock, and very likely Work item A. This is the keystone.
This is a FEATURE → start with superpowers:brainstorming (the user is the retail oracle on look/feel).
Research first: grep docs/research/named-retail/acclient_2013_pseudo_c.txt for the portal/teleport flow
— the teleport animation, the loading hold, the PortalSpace exit condition, and the unified path for
login/logout/death/portal. Extend, don't rebuild: acdream already has PlayerState.PortalSpace,
TeleportArrivalController, and TeleportArrivalRules.Decide (src/AcDream.App/World/ + GameWindow); the
flow should slot the anim + hold-until-loaded into that machinery.
Work item C — FPS leak after teleports (perf bug, SEPARATE)
Symptom: FPS drops low after a couple of teleports (cumulative).
Hypothesis: a streaming/entity leak — landblocks or render/physics entities not freed on teleport,
accumulating across round-trips (candidates: dungeon collapse/expand not cleaning up; RehydrateServerEntities
/ _lastSpawnByGuid accumulating; GpuWorldState entities not pruned). NEXT: capture FPS + landblock /
entity counts across N teleports (ACDREAM_DUMP_LIVE_SPAWNS=1 + streaming logs + the DebugPanel counts), find
what grows unbounded. Independent of A and B.
Pointers / apparatus
- Logs (worktree root):
launch5.log(#145 residual capture — the0xC98Cstuck-at-−21684run),launch4.log(Z free-fall + a 3-far-town round-trip),launch3/launch2(clean streamed-arrival runs). - #145 record:
docs/ISSUES.md#145 (reopened, with the trigger table) + the physics digest banner (claude-memory/project_physics_collision_digest.md). - Probes (no rebuild):
ACDREAM_PROBE_CELL=1([cell-transit]),ACDREAM_PROBE_RESOLVE=1,ACDREAM_CAPTURE_RESOLVE=<path>,ACDREAM_DUMP_LIVE_SPAWNS=1. - Decomp oracle:
docs/research/named-retail/(grepclass::method); for the teleport flow, look at the portal/teleport + DDD-loading + animation paths. - Wire cross-check:
references/holtburger(client teleport flow) +references/ACE(server teleport /MOVEMENT SPEEDvalidation — thefailed transitionrejects).
Suggested order (brainstorm to confirm)
- B first (retail teleport flow) — it's the keystone and likely subsumes A. Brainstorm → spec → build.
- Re-test A: if the hold-until-loaded flow eliminates the unstreamed gap, the #145 residual is gone; if a narrow edge case survives, apply the diagnostic + targeted hold.
- C (FPS leak) — independent; can run in parallel as its own investigation.
- (Background) Slices 4–6 — the invisible Option-B completeness, unrelated to this cluster.