feat(core): add WorldView with 3x3 neighbor landblock computation
This commit is contained in:
parent
8f5b498be6
commit
5d35f4fe46
2 changed files with 101 additions and 0 deletions
55
src/AcDream.Core/World/WorldView.cs
Normal file
55
src/AcDream.Core/World/WorldView.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
tests/AcDream.Core.Tests/World/WorldViewTests.cs
Normal file
46
tests/AcDream.Core.Tests/World/WorldViewTests.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
// tests/AcDream.Core.Tests/World/WorldViewTests.cs
|
||||||
|
using AcDream.Core.World;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.World;
|
||||||
|
|
||||||
|
public class WorldViewTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void NeighborIds_Center_Returns9Ids()
|
||||||
|
{
|
||||||
|
var ids = WorldView.NeighborLandblockIds(0xA9B4FFFFu).ToList();
|
||||||
|
|
||||||
|
Assert.Equal(9, ids.Count);
|
||||||
|
Assert.Contains(0xA9B4FFFFu, ids); // center
|
||||||
|
Assert.Contains(0xA8B3FFFFu, ids); // NW
|
||||||
|
Assert.Contains(0xAAB5FFFFu, ids); // SE
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NeighborIds_LowerEdge_ClampsUnderflow()
|
||||||
|
{
|
||||||
|
// Landblock 0x0000FFFF — no west or south neighbors.
|
||||||
|
var ids = WorldView.NeighborLandblockIds(0x0000FFFFu).ToList();
|
||||||
|
|
||||||
|
// 4 neighbors should exist: center + E + N + NE
|
||||||
|
Assert.Equal(4, ids.Count);
|
||||||
|
Assert.Contains(0x0000FFFFu, ids);
|
||||||
|
Assert.Contains(0x0100FFFFu, ids);
|
||||||
|
Assert.Contains(0x0001FFFFu, ids);
|
||||||
|
Assert.Contains(0x0101FFFFu, ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NeighborIds_UpperEdge_ClampsOverflow()
|
||||||
|
{
|
||||||
|
// Landblock 0xFFFFFFFF — no east or north neighbors.
|
||||||
|
var ids = WorldView.NeighborLandblockIds(0xFFFFFFFFu).ToList();
|
||||||
|
|
||||||
|
// 4 neighbors: center + W + S + SW
|
||||||
|
Assert.Equal(4, ids.Count);
|
||||||
|
Assert.Contains(0xFFFFFFFFu, ids);
|
||||||
|
Assert.Contains(0xFEFFFFFFu, ids);
|
||||||
|
Assert.Contains(0xFFFEFFFFu, ids);
|
||||||
|
Assert.Contains(0xFEFEFFFFu, ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue