fix(physics): #146 — re-base building collision per landblock apply (lost after portal-in)

Static building/house-wall collision worked on a fresh login to a town but was
lost after logging in elsewhere and PORTALING in: the foot-sphere clipped
straight through walls while server-spawned doors (own collision) still blocked.

Root (capture-confirmed, ACDREAM_PROBE_BUILDING bldOrigin): the building shell
BSP's WorldTransform is computed from the streaming-relative origin
(origin = (lb − _liveCenter)·192) AT CACHE TIME, and CacheBuilding is idempotent
(first-wins per cell). A teleport recenters _liveCenter, but the idempotent guard
never re-bases the cached transform — so the shell sat at a stale world offset
(login Arwic → portal Holtburg: bldOrigin=(-5488,2149), ~5.5 km from the player
at (83,24)), and FindBuildingCollisions never penetrated → result=OK everywhere →
no block. Terrain doesn't suffer this because AddLandblock overwrites its
WorldOffset on every apply.

Fix: clear a landblock's cached buildings at the start of each ApplyLoadedTerrain
(PhysicsDataCache.RemoveBuildingsForLandblock), then let the existing loop
re-populate fresh with the CURRENT origin — the per-apply re-base terrain already
gets, while keeping CacheBuilding's per-cell first-wins within each fresh pass
(retail CSortCell::add_building). Also adds bldOrigin to the [bldg-channel] probe.

Verified on the exact repro (Arwic login → Holtburg portal → walk into wall):
bldOrigin now (107.5,36.0) at the wall (was -5488,2149); channel returns
Collided → Slid (block + wall-slide). Suites green: Core 1568(+2 skip),
App 468(+2 skip), UI 425, Net 317.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-24 13:33:06 +02:00
parent 5b3e946b8b
commit 49d743f88a
3 changed files with 34 additions and 1 deletions

View file

@ -6943,6 +6943,17 @@ public sealed class GameWindow : IDisposable
// formula (gridX * 8 + gridY + 1) within the 192m × 192m landblock.
if (lbInfo is not null && lbInfo.Buildings.Count > 0)
{
// #146 (2026-06-24): clear this landblock's prior building cache so
// the loop re-bases each building's STREAMING-RELATIVE WorldTransform
// with the CURRENT _liveCenter (origin, recomputed above per apply).
// CacheBuilding's per-cell first-wins then applies fresh within this
// pass — mirrors terrain's per-apply WorldOffset re-base (AddLandblock).
// Without it, CacheBuilding's idempotent guard locks the transform at
// the frame it was first cached with, so a teleport recenter strands
// the shell BSP at a stale world offset and house walls stop colliding
// (login at Arwic → portal to Holtburg → walls clip; bldOrigin ~5.5km off).
_physicsDataCache.RemoveBuildingsForLandblock(lb.LandblockId);
uint lbPrefix = lb.LandblockId & 0xFFFF0000u;
foreach (var building in lbInfo.Buildings)
{