phase(N.1): add LandBlock → TerrainEntry[] adapter

Phase N.1 step 1: WbSceneryAdapter.BuildTerrainEntries converts our
LandBlock dat type into the TerrainEntry[81] shape WorldBuilder's
TerrainUtils / SceneryRenderManager consume.

Field mapping (TerrainInfo → TerrainEntry):
  TerrainInfo.Road    (bits 0-1)   → TerrainEntry.Road
  TerrainInfo.Type    (bits 2-6)   → TerrainEntry.Type
  TerrainInfo.Scenery (bits 11-15) → TerrainEntry.Scenery
  LandBlock.Height[i]              → TerrainEntry.Height

The spec listed the texture property as 'Texture' but TerrainEntry's
actual property is named 'Type' (confirmed from source). The spec also
described LandBlock.Terrain as ushort[81] but it is TerrainInfo[81] —
DatReaderWriter already decodes the bit fields so the adapter uses
TerrainInfo's named properties rather than raw bit-shift expressions.

Spec: docs/superpowers/specs/2026-05-08-phase-n1-scenery-via-wb-helpers-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-08 09:11:59 +02:00
parent 21425ffb22
commit 26cf2b84e7
2 changed files with 119 additions and 0 deletions

View file

@ -0,0 +1,45 @@
using DatReaderWriter.DBObjs;
using WorldBuilder.Shared.Models;
namespace AcDream.Core.World;
/// <summary>
/// Bridges acdream's dat types into WorldBuilder's data shapes for the
/// Phase N rendering migration. See
/// <c>docs/architecture/worldbuilder-inventory.md</c> for the full strategy.
/// </summary>
internal static class WbSceneryAdapter
{
private const int VerticesPerSide = 9;
private const int TerrainSize = VerticesPerSide * VerticesPerSide; // 81
/// <summary>
/// Builds a 9×9 = 81-entry <see cref="TerrainEntry"/> array from a
/// <see cref="LandBlock"/>'s packed terrain bits + height bytes. WB's
/// <c>TerrainUtils.OnRoad</c> / <c>GetNormal</c> / <c>GetHeight</c>
/// consume this shape.
///
/// Field mapping (<c>TerrainInfo</c> → <see cref="TerrainEntry"/>):
/// <c>TerrainInfo.Road</c> (bits 0-1) → <see cref="TerrainEntry.Road"/>
/// <c>TerrainInfo.Type</c> (bits 2-6) → <see cref="TerrainEntry.Type"/>
/// <c>TerrainInfo.Scenery</c> (bits 11-15) → <see cref="TerrainEntry.Scenery"/>
/// <c>LandBlock.Height[i]</c> → <see cref="TerrainEntry.Height"/>
/// </summary>
public static TerrainEntry[] BuildTerrainEntries(LandBlock block)
{
ArgumentNullException.ThrowIfNull(block);
var entries = new TerrainEntry[TerrainSize];
for (int i = 0; i < TerrainSize; i++)
{
var ti = block.Terrain[i];
entries[i] = new TerrainEntry(
height: block.Height[i],
texture: (byte)ti.Type,
scenery: ti.Scenery,
road: ti.Road,
encounters: null);
}
return entries;
}
}