diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 6c26170..ac17ed8 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -1863,7 +1863,7 @@ public sealed class GameWindow : IDisposable _terrain?.RemoveLandblock(id); _physicsEngine.RemoveLandblock(id); _cellVisibility.RemoveLandblock((id >> 16) & 0xFFFFu); - _buildingRegistries.Remove(id); // Phase A8 + _buildingRegistries.Remove(id & 0xFFFF0000u); // Phase A8 RR7.2: masked key matches storage }); // A.5 T22.5: apply max-completions from resolved quality. _streamingController.MaxCompletionsPerFrame = _resolvedQuality.MaxCompletionsPerFrame; @@ -5872,7 +5872,7 @@ public sealed class GameWindow : IDisposable _physicsEngine.AddLandblock(lb.LandblockId, terrainSurface, cellSurfaces, portalPlanes, origin.X, origin.Y); - // Phase A8 (2026-05-26, fixed 2026-05-27 RR7.1): build per-landblock + // Phase A8 (2026-05-26, fixed 2026-05-27 RR7.2): build per-landblock // BuildingRegistry from LandBlockInfo.Buildings, stamping // LoadedCell.BuildingId for each cell in a building's cell set. // Uses _cellVisibility.AllLoadedCells (every cell loaded so far, @@ -5881,9 +5881,19 @@ public sealed class GameWindow : IDisposable // pass get stamped at drain time (see _pendingCells loop above). // Cells without a building stay at BuildingId == null (outdoor // surface cells; dungeon cells not in LandBlockInfo.Buildings). + // + // KEY NORMALIZATION (RR7.2): lb.LandblockId is the LandBlock file + // id (e.g. 0xA9B4FFFF — the 0xFFFF low word is the dat-file + // discriminator), but cell ids like 0xA9B40150 mask to + // 0xA9B40000. All lookups (drain late-stamp at line ~5708, gate + // check at line ~7090) use `& 0xFFFF0000u`, so storage MUST use + // the same masked form or every lookup misses — which silently + // routed every indoor frame through the outdoor branch in the + // RR7.1 launch. if (lbInfo is not null) { - _buildingRegistries[lb.LandblockId] = + uint lbRegistryKey = lb.LandblockId & 0xFFFF0000u; + _buildingRegistries[lbRegistryKey] = AcDream.App.Rendering.Wb.BuildingLoader.Build( lbInfo, lb.LandblockId, _cellVisibility.AllLoadedCells); } @@ -9083,7 +9093,7 @@ public sealed class GameWindow : IDisposable _terrain?.RemoveLandblock(id); _physicsEngine.RemoveLandblock(id); _cellVisibility.RemoveLandblock((id >> 16) & 0xFFFFu); - _buildingRegistries.Remove(id); // Phase A8 + _buildingRegistries.Remove(id & 0xFFFF0000u); // Phase A8 RR7.2: masked key }); _streamingController.MaxCompletionsPerFrame = newResolved.MaxCompletionsPerFrame;