From 5b3e946b8bd0d597380ab1c4099b25b512cd1a20 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Jun 2026 13:11:42 +0200 Subject: [PATCH] docs(issues): file #146/#147 (post-portal + far-town wall collision) + record #138-B avatar-vanish fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue A ("no collision after death/portal") investigated capture-first and confirmed to be TWO distinct bugs (user-corroborated + ACDREAM_CAPTURE_RESOLVE data, 255,832 player resolves): - #147 (HIGH) far-town (Arwic): grounded only 3% of resolves vs 100% at Holtburg/dungeon; city/perimeter walls never block even on a fresh login — the #145 streaming-relative-frame family. Scope as a brainstormed #145 sub-phase, not a one-commit fix. - #146 (MEDIUM) Holtburg: building/house-wall collision works on fresh login but is lost after portaling in. The [bldg-channel] probe fires post-portal (building is cached + reached) yet result=OK as the foot-sphere walks into the wall — the building WorldTransform is baked from _liveCenter at cache time and CacheBuilding is idempotent, so the recenter leaves a stale offset. Also recorded against #138 that symptom B (avatar vanish) was root-caused and fixed in afd5f2a (RelocateEntity-during-PortalSpace), not just the pending- bucket rescue candidate. No guess-patches applied to the collision code (DO-NOT-RETRY area). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/ISSUES.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 2fbe3a92..6b2a22f7 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -46,6 +46,46 @@ Copy this block when adding a new issue: --- +## #147 — Far-town (Arwic) collision broken at login: terrain barely grounds + city/perimeter walls never block + +**Status:** OPEN +**Severity:** HIGH (collision largely absent in far towns; #145-frame family) +**Filed:** 2026-06-24 +**Component:** physics — far-town streaming-relative collision frame (#145 family) + +**Description (user-observed 2026-06-24):** In Arwic (a far town reached via the Town Network), the city/perimeter walls have NO collision even on a FRESH login there — not portal-churn, it's fundamental. Buildings' own collision channel does fire (`[bldg-channel]` emits at Arwic), but the player walks through the city walls and the terrain barely grounds. Distinct from #146 (which is portal-in-only at Holtburg). + +**Root cause (capture-confirmed symptom; #145-family root):** The `ACDREAM_CAPTURE_RESOLVE` capture (`a-wall-resolve.jsonl`, 255,832 player resolves) shows the player is grounded only **3% of resolves at Arwic (0xC6A9)** vs **100% at Holtburg/dungeon** — the terrain collision query misses the ground almost entirely (the player doesn't fall only because zero-move resolves return the "no terrain loaded → pass-through" branch instead of a contact plane). This is the streaming-relative-frame misalignment at a far town: positions are stored relative to `_liveCenter`, the far-town frame/origin is wrong, so terrain + static-wall collision queries hit the wrong place. The physics digest already names the fix as **#145 Option B** — port retail's cell-relative `Position` frame and make `_liveCenter` render-only (multi-commit, brainstorm-gated). The city-perimeter-wall static class may also need its own collision-registration check. + +**Files:** `src/AcDream.Core/Physics/CellTransit.cs` (outdoor pick + `TryGetTerrainOrigin` frame), `src/AcDream.Core/Physics/PhysicsEngine.cs` (terrain sample/frame), `src/AcDream.App/Rendering/GameWindow.cs` (`_liveCenter` placement seam). + +**Research:** capture `a-wall-resolve.jsonl` (Arwic 3% grounded vs Holtburg 100%); `claude-memory/project_physics_collision_digest.md` #145 banner; `docs/research/2026-06-21-145-cell-relative-physics-frame-handoff.md`. **SCOPE AS A BRAINSTORMED #145 SUB-PHASE — not a one-commit fix; no guess-patches (DO-NOT-RETRY collision area).** + +**Acceptance:** in a far town (Arwic), terrain grounds like Holtburg (~100% of resolves) and city/perimeter walls block — matching retail. + +--- + +## #146 — Building/house-wall collision lost after portaling INTO a town (works on fresh login) + +**Status:** OPEN +**Severity:** MEDIUM (clip through house/building walls after every portal-in; doors still block; terrain solid) +**Filed:** 2026-06-24 +**Component:** physics — building collision channel + streaming-relative frame (teleport recenter) + +**Description (user-observed 2026-06-24):** Static building/house walls block normally on a FRESH login to a town (Holtburg confirmed), but after logging in elsewhere and PORTALING into the town, the same walls no longer block — you clip straight through. Server-spawned DOORS still block (they register their own collision via CreateObject), and terrain stays solid — so the symptom is specifically dat-static building-wall collision after a portal-in. + +**Root cause (capture-narrowed, one probe from confirmed):** The building collision channel (`TransitionTypes.FindBuildingCollisions` → `PhysicsDataCache.GetBuilding(cellId)` → BSP test vs `BuildingPhysics.WorldTransform`) IS reached after a portal-in — the `[bldg-channel]` probe fires at Holtburg post-portal (`cell=0xA9B40022 model=0x01000C17`) — but every test returns `result=OK` (no penetration) as the foot-sphere walks into the wall (`arwic-to-holtburg-bldg-capture.log`). The building's `WorldTransform` is computed from `_liveCenter` AT CACHE TIME (`GameWindow.cs` ~6969: `building.Frame.Origin + origin`, `origin = (lb − _liveCenter)·192`) and `CacheBuilding` is IDEMPOTENT (`PhysicsDataCache.cs:444` `if (_buildings.ContainsKey) return;` — never re-cached, never cleared on unload). A teleport recenters `_liveCenter`, so the cached shell BSP can sit at a stale world offset → the sphere never penetrates → no block. Same streaming-relative-frame family as #145/#147. + +**Next step (one probe before fixing):** add `building.WorldTransform.Translation` to the `[bldg-channel]` line; if it's offset from the visual building / player position after a portal-in, the stale-transform root is confirmed. Fix = invalidate `_buildings[landcell]` on `RemoveLandblock` so it re-caches with the current frame on reload (targeted), or store the transform cell-relative (the #145 frame). **No guess-patch (DO-NOT-RETRY collision area).** + +**Files:** `src/AcDream.App/Rendering/GameWindow.cs` (~6944–7003 building cache loop), `src/AcDream.Core/Physics/PhysicsDataCache.cs` (`CacheBuilding`/`GetBuilding`/`_buildings`, ~441–464), `src/AcDream.Core/Physics/TransitionTypes.cs` (`FindBuildingCollisions` 2805, `[bldg-channel]` probe 2874). + +**Research:** captures `a-wall-resolve.jsonl` (Holtburg 100% grounded, 876/882 wall-moves no block, doors collide), `arwic-to-holtburg-bldg-capture.log` (post-portal `result=OK`), `holtburg-bldg-capture.log` (fresh-login channel fires). Relates to `claude-memory/project_physics_collision_digest.md` + #145/#147. + +**Acceptance:** after portaling into Holtburg from elsewhere, building/house walls block exactly as on a fresh login. + +--- + ## #145 — Portals only work once per session (can't run in, run out, re-enter) **Status:** 🟡 PARTIALLY FIXED — REOPENED 2026-06-21 (a NARROWER residual). The cell-relative carried-anchor (Option B, Slices 1–3+7, `438bb68`→`403a338`) **fixes the cascade for a STREAMED-terrain arrival** (live-verified: `+Je` ran through ~10 far-town landblocks across 2 sessions, zero march). BUT a third live session found the cascade **RECURS when a teleport arrives onto a NOT-YET-STREAMED landblock NEAR AN EDGE.** Evidence (`launch5.log`): arrival `[snap] claim=0xC98C0028 pos=(113.666,190.259,22.010) branch=NO-LANDBLOCK (lbs=0) -> verbatim` (local Y=190.3, **1.7 m from the 192 boundary**) → cell marches `0xC98C(lbY 0x8C) → 0xC9FE(lbY 0xFE)` +2/tick while Z free-falls 22→−19; the outbound wire then sends the marched cell `C9FE0031` with compensating garbage `localY=−21684` → ACE `MOVEMENT SPEED` / `failed transition` → player stuck. Contrast same session: hub `0x00070133` VALIDATED→fine; far town `0x977B000C` arrived unstreamed but **mid-block** (Y=73.8) → Z free-fall only, NO march. **ROOT (hypothesis, NOT yet 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 that gap the resolve runs against an empty world, and 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-but-unstreamed gap). **DO NOT guess-patch** (original #145 burned 5 attempts) — needs a capture + an anchor/guard diagnostic at the crossing FIRST. Likely fix shape: a streaming-gap HOLD (freeze the per-tick resolve — no march, no fall — until the player's landblock loads; the async equivalent of retail's synchronous load), which would fix both symptoms. Suites still green; `TeleportFarTownRunawayTests` covers the STREAMED case only. [Prior "fixed" banner was premature — 2 clean sessions wasn't enough for a streaming-timing bug.] @@ -311,6 +351,8 @@ Both are the **entity-lifecycle/render path across a teleport**, NOT the streami **Implementation (B — player vanish, candidate):** `GpuWorldState.RemoveLandblock` rescued persistent entities only from `_loaded`, silently dropping a persistent entity sitting in the **pending bucket** (the player is re-injected via `AppendLiveEntity` every frame; right after a teleport its landblock hasn't streamed yet → pending; if that landblock is then unloaded mid-churn the player was dropped → "vanishes after a couple round-trips"). Fix: rescue persistent pending entries too. Tests `RemoveLandblock_RescuesPersistentEntity_FromPendingBucket` (+ negative). This is a provable correctness fix for the "persistent ⇒ survives unload" invariant; it is the leading candidate for symptom B but needs user re-verification to confirm it is the complete cause. +**UPDATE 2026-06-24 — symptom B (avatar vanish) ACTUAL root found + FIXED (`afd5f2a`, user-confirmed + trace-verified):** the pending-bucket rescue above was necessary but NOT the whole cause. The real culprit: the per-frame avatar-sync (`GameWindow` ~:8018) calls `GpuWorldState.RelocateEntity` using the player controller's cell, which stays the **FROZEN SOURCE cell** until `PlaceTeleportArrival` materializes the destination. Mid-transit it dragged the avatar — which the teleport's `DrainRescued` re-inject had correctly placed at the destination center — back into the now-UNLOADED source landblock's pending bucket, where nothing recovers it (`RelocateEntity` only scans `_loaded`). Fix: skip the per-frame relocate while `_playerController.State == PortalSpace`. Verified by a new env-gated avatar-lifecycle probe (`ACDREAM_PROBE_ENT` / `EntityVanishProbe`): pre-fix `[ent] APPEND lb=0x0007FFFF(source) -> PENDING -> DRAWSET ABSENT` never recovered; post-fix every teleport goes `RESCUE -> ABSENT -> APPEND(destination) -> PRESENT` and stays drawn. **The remaining #138 collision residual split into #146 (Holtburg portal-in building walls) + #147 (Arwic far-town frame).** + **Acceptance:** portal out of the 0x0007 dungeon → full outdoor world streams (trees/scenery present), **server objects (doors/NPCs/portals) render**, **own avatar renders across repeated round-trips**, collision works, position tracks (no avatar-vs-camera desync). ---