using static Sandbox.IByteParsable; namespace Sandbox.Navigation.Generation; internal partial class CompactHeightfield : IByteParsable { public static CompactHeightfield Read( ref ByteStream stream, ByteParseOptions o = default ) { var compactHeightfield = GetPooled(); var width = stream.Read(); var height = stream.Read(); var spanCount = stream.Read(); var walkableHeight = stream.Read(); var walkableClimb = stream.Read(); var bMin = stream.Read(); var bMax = stream.Read(); var cellSize = stream.Read(); var cellHeight = stream.Read(); compactHeightfield.Init( width, height, spanCount, walkableHeight, walkableClimb, bMin, bMax, cellSize, cellHeight ); var cells = compactHeightfield.Cells; ReadCells( ref stream, cells ); var spans = compactHeightfield.Spans; ReadSpans( ref stream, spans ); var areas = compactHeightfield.Areas; ReadAreas( ref stream, areas ); return compactHeightfield; } public static object ReadObject( ref ByteStream stream, ByteParseOptions o = default ) { return Read( ref stream, o ); } public static void Write( ref ByteStream stream, CompactHeightfield value, ByteParseOptions o = default ) { stream.Write( value.Width ); stream.Write( value.Height ); stream.Write( value.SpanCount ); stream.Write( value.WalkableHeight ); stream.Write( value.WalkableClimb ); stream.Write( value.BMin ); stream.Write( value.BMax ); stream.Write( value.CellSize ); stream.Write( value.CellHeight ); WriteCells( ref stream, value.Cells ); WriteSpans( ref stream, value.Spans ); WriteAreas( ref stream, value.Areas ); } public static void WriteObject( ref ByteStream stream, object value, ByteParseOptions o = default ) { Write( ref stream, value as CompactHeightfield, o ); } private static void ReadCells( ref ByteStream stream, Span cells ) { var spanCursor = 0; for ( var i = 0; i < cells.Length; i++ ) { var count = stream.Read(); ref var cell = ref cells[i]; cell.Index = spanCursor; cell.Count = count; spanCursor += count; } } private static void WriteCells( ref ByteStream stream, ReadOnlySpan cells ) { for ( var index = 0; index < cells.Length; index++ ) { stream.Write( (byte)cells[index].Count ); } } private static void ReadSpans( ref ByteStream stream, Span spans ) { for ( var i = 0; i < spans.Length; i++ ) { ref var span = ref spans[i]; span.StartY = stream.Read(); span.Region = stream.Read(); span.connectionsAndHeight = stream.Read(); } } private static void WriteSpans( ref ByteStream stream, ReadOnlySpan spans ) { for ( var i = 0; i < spans.Length; i++ ) { ref readonly var span = ref spans[i]; stream.Write( span.StartY ); stream.Write( span.Region ); stream.Write( span.connectionsAndHeight ); } } private static void ReadAreas( ref ByteStream stream, Span areas ) { var index = 0; while ( index < areas.Length ) { var runLength = stream.Read(); var areaValue = stream.Read(); for ( var i = 0; i < runLength && index < areas.Length; i++ ) { areas[index++] = areaValue; } } } private static void WriteAreas( ref ByteStream stream, ReadOnlySpan areas ) { var index = 0; while ( index < areas.Length ) { var areaValue = areas[index]; var runLength = 1; while ( index + runLength < areas.Length && areas[index + runLength] == areaValue ) { runLength++; } stream.Write( runLength ); stream.Write( areaValue ); index += runLength; } } }