// src/AcDream.Core/World/WorldView.cs using DatReaderWriter; namespace AcDream.Core.World; public sealed class WorldView { public uint CenterLandblockId { get; } public IReadOnlyList Landblocks { get; } public IEnumerable AllEntities => Landblocks.SelectMany(lb => lb.Entities); private WorldView(uint centerLandblockId, IReadOnlyList landblocks) { CenterLandblockId = centerLandblockId; Landblocks = landblocks; } /// /// Load the 3x3 grid of landblocks around . /// Missing neighbors (edges of the world or absent from the cell dat) are silently skipped. /// public static WorldView Load(DatCollection dats, uint centerLandblockId) { var loaded = new List(); foreach (var id in NeighborLandblockIds(centerLandblockId)) { var lb = LandblockLoader.Load(dats, id); if (lb is not null) loaded.Add(lb); } return new WorldView(centerLandblockId, loaded); } /// /// Enumerate the 3x3 neighbor landblock ids around a center. Clamps at the world edges /// (skipping neighbors that would underflow or overflow the 8-bit coordinate range). /// public static IEnumerable NeighborLandblockIds(uint centerLandblockId) { int cx = (int)((centerLandblockId >> 24) & 0xFFu); int cy = (int)((centerLandblockId >> 16) & 0xFFu); for (int dy = -1; dy <= 1; dy++) { for (int dx = -1; dx <= 1; dx++) { int nx = cx + dx; int ny = cy + dy; if (nx < 0 || nx > 0xFF || ny < 0 || ny > 0xFF) continue; yield return (uint)((nx << 24) | (ny << 16) | 0xFFFFu); } } } }