using DatReaderWriter.DBObjs; using WorldBuilder.Shared.Models; namespace AcDream.Core.World; /// /// Bridges acdream's dat types into WorldBuilder's data shapes for the /// Phase N rendering migration. See /// docs/architecture/worldbuilder-inventory.md for the full strategy. /// internal static class WbSceneryAdapter { private const int VerticesPerSide = 9; private const int TerrainSize = VerticesPerSide * VerticesPerSide; // 81 /// /// Builds a 9×9 = 81-entry array from a /// 's packed terrain bits + height bytes. WB's /// TerrainUtils.OnRoad / GetNormal / GetHeight /// consume this shape. /// /// Field mapping (TerrainInfo): /// TerrainInfo.Road (bits 0-1) → /// TerrainInfo.Type (bits 2-6) → /// TerrainInfo.Scenery (bits 11-15) → /// LandBlock.Height[i] /// /// /// No runtime length guards are needed here because /// DatReaderWriter.DBObjs.LandBlock's default constructor /// self-initializes both Terrain and Height to fixed-length /// arrays of exactly 81 elements (9×9 vertices per landblock). Any caller /// that constructs a synthetic with partial arrays /// will receive an at the first /// mis-sized index, which is the correct fast-fail behaviour for a /// contract violation of this kind. /// 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; } }