diff --git a/src/AcDream.App/Rendering/CellVisibility.cs b/src/AcDream.App/Rendering/CellVisibility.cs
index 87fdc67..d3cf6f1 100644
--- a/src/AcDream.App/Rendering/CellVisibility.cs
+++ b/src/AcDream.App/Rendering/CellVisibility.cs
@@ -176,18 +176,6 @@ public sealed class CellVisibility
/// Full-ID lookup for O(1) neighbour resolution during BFS.
private readonly Dictionary _cellLookup = new();
- ///
- /// Phase A8 RR7.1 (2026-05-27): read-only view of every loaded cell, keyed
- /// by full 32-bit cell id. Used by at
- /// landblock-info-arrival time so its BFS can reach cells that streamed
- /// in on earlier frames (not just the per-frame drain). Without this view
- /// the registry's EnvCellIds set was systematically short, leaving
- /// unset on the cells the camera
- /// actually enters — which silently routed indoor frames through the
- /// outdoor branch.
- ///
- public IReadOnlyDictionary AllLoadedCells => _cellLookup;
-
/// The cell the camera was in during the last call.
private LoadedCell? _lastCameraCell;
diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs
index 6c26170..d6ecebb 100644
--- a/src/AcDream.App/Rendering/GameWindow.cs
+++ b/src/AcDream.App/Rendering/GameWindow.cs
@@ -5696,21 +5696,12 @@ public sealed class GameWindow : IDisposable
_terrain.AddLandblockWithMesh(lb.LandblockId, meshData, origin);
// Step 4: drain pending LoadedCells from the worker thread.
- // Phase A8 RR7.1 (2026-05-27): also late-stamp BuildingId on each
- // arriving cell if the landblock's BuildingRegistry already exists
- // (cells loaded after the registry-build pass at line ~5876). Cells
- // arriving BEFORE the registry are stamped by BuildingLoader.Build
- // itself via the AllLoadedCells dict.
+ // Also collect into a local dict for the BuildingLoader stamping pass below.
+ var drainedCells = new System.Collections.Generic.Dictionary();
while (_pendingCells.TryTake(out var cell))
{
_cellVisibility.AddCell(cell);
- uint cellLbId = cell.CellId & 0xFFFF0000u;
- if (_buildingRegistries.TryGetValue(cellLbId, out var existingReg))
- {
- var bs = existingReg.GetBuildingsContainingCell(cell.CellId);
- if (bs.Count > 0)
- cell.BuildingId = bs[0].BuildingId;
- }
+ drainedCells[cell.CellId] = cell;
}
// Compute the per-landblock AABB for frustum culling. XY from the
@@ -5872,20 +5863,18 @@ 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
- // BuildingRegistry from LandBlockInfo.Buildings, stamping
- // LoadedCell.BuildingId for each cell in a building's cell set.
- // Uses _cellVisibility.AllLoadedCells (every cell loaded so far,
- // not just the per-frame drain) so the BFS can reach cells that
- // streamed in on earlier frames. Cells arriving AFTER this build
- // 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).
+ // Phase A8 (2026-05-26): build per-landblock BuildingRegistry from
+ // LandBlockInfo.Buildings, stamping LoadedCell.BuildingId for each cell
+ // in a building's cell set. Uses the already-drained drainedCells dict
+ // (LoadedCells registered this frame) so stamping and registry build
+ // happen in the same render-thread pass — no extra dat reads required.
+ // Cells without a building stay at BuildingId == null (outdoor surface
+ // cells; dungeon cells not enumerated in LandBlockInfo.Buildings).
if (lbInfo is not null)
{
_buildingRegistries[lb.LandblockId] =
AcDream.App.Rendering.Wb.BuildingLoader.Build(
- lbInfo, lb.LandblockId, _cellVisibility.AllLoadedCells);
+ lbInfo, lb.LandblockId, drainedCells);
}
}