feat(core): add WorldView with 3x3 neighbor landblock computation

This commit is contained in:
Erik 2026-04-10 18:02:41 +02:00
parent 8f5b498be6
commit 5d35f4fe46
2 changed files with 101 additions and 0 deletions

View file

@ -0,0 +1,55 @@
// src/AcDream.Core/World/WorldView.cs
using DatReaderWriter;
namespace AcDream.Core.World;
public sealed class WorldView
{
public uint CenterLandblockId { get; }
public IReadOnlyList<LoadedLandblock> Landblocks { get; }
public IEnumerable<WorldEntity> AllEntities => Landblocks.SelectMany(lb => lb.Entities);
private WorldView(uint centerLandblockId, IReadOnlyList<LoadedLandblock> landblocks)
{
CenterLandblockId = centerLandblockId;
Landblocks = landblocks;
}
/// <summary>
/// Load the 3x3 grid of landblocks around <paramref name="centerLandblockId"/>.
/// Missing neighbors (edges of the world or absent from the cell dat) are silently skipped.
/// </summary>
public static WorldView Load(DatCollection dats, uint centerLandblockId)
{
var loaded = new List<LoadedLandblock>();
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);
}
/// <summary>
/// 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).
/// </summary>
public static IEnumerable<uint> 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);
}
}
}
}