using System; using System.Collections.Generic; namespace AcDream.App.Rendering.Wb; /// /// Phase A8 (2026-05-26): per-landblock registry of s. /// Two-way indexed for O(1) cell→building and building-id→building lookups. /// Built once per landblock at load time by ; /// no mutations occur after initial population. /// /// The cell→building index uses a List<Building> value type /// to handle the (rare but valid) case where two buildings share an EnvCell — /// each building performs its own BFS so a shared boundary cell ends up in both /// EnvCellIds sets. returns all /// owners so RR7's render path can pick the correct one. /// /// WB reference: WorldBuilder.Shared/Services/PortalService.cs /// (BuildingPortalGroup). Design: /// docs/superpowers/specs/2026-05-26-phase-a8-wb-full-port-design.md. /// public sealed class BuildingRegistry { // Index 1: cell-id → list of buildings containing that cell. // Cells may belong to multiple buildings (rare; handled via List). private readonly Dictionary> _byCellId = new(); // Index 2: building-id → Building. private readonly Dictionary _byBuildingId = new(); /// /// Adds a building to both indexes. Idempotent if the exact same /// instance is added twice with the same /// . /// /// The building to register. public void Add(Building b) { if (_byBuildingId.TryGetValue(b.BuildingId, out var existing) && ReferenceEquals(existing, b)) return; _byBuildingId[b.BuildingId] = b; foreach (var cellId in b.EnvCellIds) { if (!_byCellId.TryGetValue(cellId, out var list)) { list = new List(); _byCellId[cellId] = list; } if (!list.Contains(b)) list.Add(b); } } /// /// Returns the buildings containing . /// Returns an empty read-only list when the cell isn't part of any /// building (outdoor cells, dungeon cells not tagged by /// LandBlockInfo.Buildings). /// /// Full 32-bit cell id. public IReadOnlyList GetBuildingsContainingCell(uint cellId) => _byCellId.TryGetValue(cellId, out var list) ? list : Array.Empty(); /// Returns the building with the given id, or null if not found. /// The building id as allocated by . public Building? GetById(uint buildingId) => _byBuildingId.TryGetValue(buildingId, out var b) ? b : null; /// Enumerates every registered building in unspecified order. public IEnumerable All() => _byBuildingId.Values; /// Number of registered buildings. public int Count => _byBuildingId.Count; }