From 2055a3e27b924f93538c5ec834bd2171b42b1146 Mon Sep 17 00:00:00 2001 From: Junior Ortiz Cabrera Date: Fri, 26 Sep 2025 11:23:12 -0500 Subject: [PATCH 1/5] Single Palette storage & start containers at 0 bpe --- Obsidian.API/ChunkData/DataContainer.cs | 75 +++++++++++++++++-- .../Palettes}/BaseIndirectPalette.cs | 13 +++- Obsidian/ChunkData/BiomeContainer.cs | 26 +------ Obsidian/ChunkData/BlockStateContainer.cs | 56 ++------------ Obsidian/ChunkData/ChunkSection.cs | 2 +- Obsidian/ChunkData/DataContainer.cs | 1 - Obsidian/ChunkData/GlobalBiomePalette.cs | 7 +- Obsidian/ChunkData/GlobalBlockStatePalette.cs | 14 +--- Obsidian/ChunkData/Heightmap.cs | 6 -- Obsidian/ChunkData/IndirectPalette.cs | 5 +- Obsidian/ChunkData/InternalIndirectPalette.cs | 6 +- Obsidian/ChunkData/Palette.cs | 14 ++-- Obsidian/WorldData/Chunk.cs | 2 +- Obsidian/WorldData/Region.cs | 16 ++-- 14 files changed, 114 insertions(+), 129 deletions(-) rename {Obsidian/ChunkData => Obsidian.API/ChunkData/Palettes}/BaseIndirectPalette.cs (93%) delete mode 100644 Obsidian/ChunkData/DataContainer.cs delete mode 100644 Obsidian/ChunkData/Heightmap.cs diff --git a/Obsidian.API/ChunkData/DataContainer.cs b/Obsidian.API/ChunkData/DataContainer.cs index 11f1ac02c..b5ca0bfed 100644 --- a/Obsidian.API/ChunkData/DataContainer.cs +++ b/Obsidian.API/ChunkData/DataContainer.cs @@ -1,17 +1,35 @@ using Obsidian.API.Utilities; +using System.Threading; namespace Obsidian.API.ChunkData; + public abstract class DataContainer { - public bool IsEmpty { get; } - public byte BitsPerEntry => (byte)DataArray.BitsPerEntry; + private readonly Lock storageLock = new(); + + public int EntryCount { get; protected set; } + + public virtual bool IsEmpty { get; } + public byte BitsPerEntry => (byte)this.Palette.BitCount; public abstract IPalette Palette { get; internal set; } - internal abstract DataArray DataArray { get; private protected set; } + internal virtual DataArray DataArray { get; private protected set; } public virtual int GetIndex(int x, int y, int z) => (y << this.BitsPerEntry | z) << this.BitsPerEntry | x; + public DataContainer(int entryCount, IPalette palette) + { + this.EntryCount = entryCount; + this.Palette = palette; + this.DataArray = BitsPerEntry != 0 ? new DataArray(BitsPerEntry, entryCount) : null; + } + + public DataContainer(int entryCount, IPalette palette, T defaultValue) : this(entryCount, palette) + { + this.Palette.GetOrAddId(defaultValue); + } + public void GrowDataArray() { if (Palette.BitCount <= DataArray.BitsPerEntry) @@ -20,11 +38,56 @@ public void GrowDataArray() DataArray = DataArray.Grow(Palette.BitCount); } - public abstract void Set(int x, int y, int z, T blockState); + public void InitializeDataArray() + { + if (this.Palette.BitCount == 0) + return; + + this.DataArray = new DataArray(this.Palette.BitCount, this.EntryCount); + } + + public virtual void Set(int x, int y, int z, T blockState) + { + lock (this.storageLock) + { + var blockIndex = GetIndex(x, y, z); - public abstract T Get(int x, int y, int z); + int paletteId = Palette.GetOrAddId(blockState); - public abstract void WriteTo(INetStreamWriter writer); + if (this.Palette.BitCount == 0) + return; + + DataArray ??= new DataArray(this.Palette.BitCount, this.EntryCount); + + this.GrowDataArray(); + + DataArray[blockIndex] = paletteId; + } + } + + public virtual T Get(int x, int y, int z) + { + lock (this.storageLock) + { + if (this.Palette.BitCount == 0) + return Palette.GetValueFromIndex(0); + + var index = GetIndex(x, y, z); + int storageId = DataArray[index]; + + return Palette.GetValueFromIndex(storageId); + } + } + + public virtual void WriteTo(INetStreamWriter writer) + { + writer.WriteByte(this.BitsPerEntry); + + this.Palette.WriteTo(writer); + + if (this.DataArray != null) + writer.WriteLongArray(this.DataArray.storage); + } public abstract DataContainer Clone(); } diff --git a/Obsidian/ChunkData/BaseIndirectPalette.cs b/Obsidian.API/ChunkData/Palettes/BaseIndirectPalette.cs similarity index 93% rename from Obsidian/ChunkData/BaseIndirectPalette.cs rename to Obsidian.API/ChunkData/Palettes/BaseIndirectPalette.cs index 0d3a6f27a..a0e6d5a30 100644 --- a/Obsidian/ChunkData/BaseIndirectPalette.cs +++ b/Obsidian.API/ChunkData/Palettes/BaseIndirectPalette.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace Obsidian.ChunkData; +namespace Obsidian.API.ChunkData.Palettes; public abstract class BaseIndirectPalette : IPalette { @@ -81,10 +81,16 @@ public virtual IPalette Clone() public void WriteTo(INetStreamWriter writer) { - writer.WriteVarInt(Count); - ReadOnlySpan values = GetSpan(); + if (this.BitCount == 0) + { + writer.WriteVarInt(values[0]); + return; + } + + writer.WriteVarInt(Count); + for (int i = 0; i < values.Length; ++i) writer.WriteVarInt(values[i]); } @@ -95,3 +101,4 @@ protected ReadOnlySpan GetSpan() return MemoryMarshal.CreateReadOnlySpan(ref first, Count); } } + diff --git a/Obsidian/ChunkData/BiomeContainer.cs b/Obsidian/ChunkData/BiomeContainer.cs index 02b462f32..76fafa416 100644 --- a/Obsidian/ChunkData/BiomeContainer.cs +++ b/Obsidian/ChunkData/BiomeContainer.cs @@ -6,36 +6,14 @@ public sealed class BiomeContainer : DataContainer internal override DataArray DataArray { get; private protected set; } - internal BiomeContainer(byte bitsPerEntry = 2) - { - this.Palette = bitsPerEntry.DetermineBiomePalette(); - this.DataArray = new(bitsPerEntry, 64); - } + internal BiomeContainer(byte bitsPerEntry = 0) : base(64, bitsPerEntry.DetermineBiomePalette(), Biome.Plains) { } - private BiomeContainer(IPalette palette, DataArray dataArray) + private BiomeContainer(IPalette palette, DataArray dataArray) : base(64, palette) { Palette = palette; DataArray = dataArray; } - public override void Set(int x, int y, int z, Biome biome) - { - var index = this.GetIndex(x, y, z); - - var paletteIndex = this.Palette.GetOrAddId(biome); - - this.GrowDataArray(); - - this.DataArray[index] = paletteIndex; - } - - public override Biome Get(int x, int y, int z) - { - var storageId = this.DataArray[this.GetIndex(x, y, z)]; - - return this.Palette.GetValueFromIndex(storageId); - } - public override void WriteTo(INetStreamWriter writer) { writer.WriteByte(this.BitsPerEntry); diff --git a/Obsidian/ChunkData/BlockStateContainer.cs b/Obsidian/ChunkData/BlockStateContainer.cs index 4c5f55f68..b57640bfb 100644 --- a/Obsidian/ChunkData/BlockStateContainer.cs +++ b/Obsidian/ChunkData/BlockStateContainer.cs @@ -4,77 +4,31 @@ public sealed class BlockStateContainer : DataContainer { public override IPalette Palette { get; internal set; } - public bool IsEmpty => DataArray.storage.Length == 0; + public override bool IsEmpty => DataArray.storage.Length == 0; - internal override DataArray DataArray { get; private protected set; } + internal BlockStateContainer(byte bitsPerEntry = 0) : base(4096, bitsPerEntry.DetermineBlockPalette(), BlocksRegistry.Air) { } - -#if CACHE_VALID_BLOCKS - private readonly DirtyCache validBlockCount; -#endif - - internal BlockStateContainer(byte bitsPerEntry = 4) - { - DataArray = new DataArray(bitsPerEntry, 4096); - Palette = bitsPerEntry.DetermineBlockPalette(); - -#if CACHE_VALID_BLOCKS - validBlockCount = new(GetNonAirBlocks); -#endif - } - - private BlockStateContainer(IPalette palette, DataArray dataArray) + private BlockStateContainer(IPalette palette, DataArray dataArray) : base(4096, palette) { Palette = palette; DataArray = dataArray; - -#if CACHE_VALID_BLOCKS - validBlockCount = new(GetNonAirBlocks); -#endif - } - - public override void Set(int x, int y, int z, IBlock blockState) - { -#if CACHE_VALID_BLOCKS - validBlockCount.SetDirty(); -#endif - var blockIndex = GetIndex(x, y, z); - - int paletteId = Palette.GetOrAddId(blockState); - - this.GrowDataArray(); - - DataArray[blockIndex] = paletteId; - } - - public override IBlock Get(int x, int y, int z) - { - int storageId = DataArray[GetIndex(x, y, z)]; - - return Palette.GetValueFromIndex(storageId); } public override void WriteTo(INetStreamWriter writer) { -#if CACHE_VALID_BLOCKS - var validBlocks = validBlockCount.GetValue(); -#else var validBlocks = GetNonAirBlocks(); -#endif writer.WriteShort(validBlocks); writer.WriteByte(BitsPerEntry); Palette.WriteTo(writer); - writer.WriteLongArray(DataArray.storage); + if (this.DataArray != null) + writer.WriteLongArray(DataArray.storage); } public void Fill(IBlock block) { -#if CACHE_VALID_BLOCKS - validBlockCount.SetDirty(); -#endif int index = Palette.GetOrAddId(block); for (int i = 0; i < 16 * 16 * 16; i++) { diff --git a/Obsidian/ChunkData/ChunkSection.cs b/Obsidian/ChunkData/ChunkSection.cs index fa7a0895b..651a8575f 100644 --- a/Obsidian/ChunkData/ChunkSection.cs +++ b/Obsidian/ChunkData/ChunkSection.cs @@ -21,7 +21,7 @@ public sealed class ChunkSection : IChunkSection private byte[] blockLight = new byte[2048]; - public ChunkSection(byte bitsPerBlock = 4, byte bitsPerBiome = 2, int? yBase = null) + public ChunkSection(byte bitsPerBlock = 0, byte bitsPerBiome = 0, int? yBase = null) { this.BlockStateContainer = new BlockStateContainer(bitsPerBlock); this.BiomeContainer = new BiomeContainer(bitsPerBiome); diff --git a/Obsidian/ChunkData/DataContainer.cs b/Obsidian/ChunkData/DataContainer.cs deleted file mode 100644 index 71465ca05..000000000 --- a/Obsidian/ChunkData/DataContainer.cs +++ /dev/null @@ -1 +0,0 @@ -namespace Obsidian.ChunkData; diff --git a/Obsidian/ChunkData/GlobalBiomePalette.cs b/Obsidian/ChunkData/GlobalBiomePalette.cs index d5815ad13..bebe6ed30 100644 --- a/Obsidian/ChunkData/GlobalBiomePalette.cs +++ b/Obsidian/ChunkData/GlobalBiomePalette.cs @@ -3,15 +3,10 @@ public class GlobalBiomePalette : IPalette { public int[] Values => throw new NotSupportedException(); - public int BitCount { get; } + public int BitCount { get; } = CodecRegistry.Biomes.GlobalBitsPerEntry; public int Count => throw new NotSupportedException(); public bool IsFull => false; - public GlobalBiomePalette(int bitCount) - { - this.BitCount = bitCount; - } - public bool TryGetId(Biome biome, out int id) { id = (int)biome; diff --git a/Obsidian/ChunkData/GlobalBlockStatePalette.cs b/Obsidian/ChunkData/GlobalBlockStatePalette.cs index 0a91fa235..68898d6ef 100644 --- a/Obsidian/ChunkData/GlobalBlockStatePalette.cs +++ b/Obsidian/ChunkData/GlobalBlockStatePalette.cs @@ -1,21 +1,13 @@ -using Obsidian.Net; -using Obsidian.Registries; +namespace Obsidian.ChunkData; -namespace Obsidian.ChunkData; - -public class GlobalBlockStatePalette : IPalette +public class GlobalBlockStatePalette() : IPalette { public int[] Values => throw new NotSupportedException(); - public int BitCount { get; } + public int BitCount { get; } = 15; public int Count => throw new NotSupportedException(); public bool IsFull => false; - public GlobalBlockStatePalette(int bitCount) - { - this.BitCount = bitCount; - } - public bool TryGetId(IBlock block, out int id) { id = block.GetHashCode(); diff --git a/Obsidian/ChunkData/Heightmap.cs b/Obsidian/ChunkData/Heightmap.cs deleted file mode 100644 index a2c0c6385..000000000 --- a/Obsidian/ChunkData/Heightmap.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Obsidian.Utilities.Collections; -using Obsidian.WorldData; - -namespace Obsidian.ChunkData; - -//TODO make better impl of heightmaps diff --git a/Obsidian/ChunkData/IndirectPalette.cs b/Obsidian/ChunkData/IndirectPalette.cs index 0be757922..caac743de 100644 --- a/Obsidian/ChunkData/IndirectPalette.cs +++ b/Obsidian/ChunkData/IndirectPalette.cs @@ -1,8 +1,9 @@ -using Obsidian.Exceptions; +using Obsidian.API.ChunkData.Palettes; +using Obsidian.Exceptions; namespace Obsidian.ChunkData; -public sealed class IndirectPalette : BaseIndirectPalette, IPalette +public sealed class IndirectPalette : BaseIndirectPalette { public IndirectPalette(byte bitCount) : base(bitCount) { diff --git a/Obsidian/ChunkData/InternalIndirectPalette.cs b/Obsidian/ChunkData/InternalIndirectPalette.cs index 14f52e69a..12cb8866d 100644 --- a/Obsidian/ChunkData/InternalIndirectPalette.cs +++ b/Obsidian/ChunkData/InternalIndirectPalette.cs @@ -1,7 +1,9 @@ -using System.Runtime.CompilerServices; +using Obsidian.API.ChunkData.Palettes; +using System.Runtime.CompilerServices; namespace Obsidian.ChunkData; -internal sealed class InternalIndirectPalette : BaseIndirectPalette, IPalette where T : struct + +internal sealed class InternalIndirectPalette : BaseIndirectPalette where T : struct { public InternalIndirectPalette(byte bitCount) : base(bitCount) { diff --git a/Obsidian/ChunkData/Palette.cs b/Obsidian/ChunkData/Palette.cs index c30f6503f..d8eca4b74 100644 --- a/Obsidian/ChunkData/Palette.cs +++ b/Obsidian/ChunkData/Palette.cs @@ -1,6 +1,4 @@ -using Obsidian.Registries; - -namespace Obsidian.ChunkData; +namespace Obsidian.ChunkData; public static class Palette { @@ -8,17 +6,17 @@ public static IPalette DetermineBlockPalette(this byte bitsPerEntry) { return bitsPerEntry switch { + 0 => new IndirectPalette(0), <= 4 => new IndirectPalette(4), > 4 and <= 8 => new IndirectPalette(bitsPerEntry), - _ => new GlobalBlockStatePalette(BlocksRegistry.GlobalBitsPerBlocks) + _ => new GlobalBlockStatePalette() }; } public static IPalette DetermineBiomePalette(this byte bitsPerEntry) { - if (bitsPerEntry <= 3) - return new InternalIndirectPalette(bitsPerEntry); - - return new GlobalBiomePalette(CodecRegistry.Biomes.GlobalBitsPerEntry); + return bitsPerEntry <= 3 + ? new InternalIndirectPalette(bitsPerEntry) + : new GlobalBiomePalette(); } } diff --git a/Obsidian/WorldData/Chunk.cs b/Obsidian/WorldData/Chunk.cs index c478affb2..4f4863470 100644 --- a/Obsidian/WorldData/Chunk.cs +++ b/Obsidian/WorldData/Chunk.cs @@ -40,7 +40,7 @@ public Chunk(int x, int z, ChunkGenStage status = ChunkGenStage.empty) Sections = new ChunkSection[24]; for (int i = 0; i < Sections.Length; i++) { - Sections[i] = new ChunkSection(4, yBase: i - 4); + Sections[i] = new ChunkSection(yBase: i - 4); } diff --git a/Obsidian/WorldData/Region.cs b/Obsidian/WorldData/Region.cs index 7a0f878b3..7137691fe 100644 --- a/Obsidian/WorldData/Region.cs +++ b/Obsidian/WorldData/Region.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using Obsidian.API.ChunkData.Palettes; using Obsidian.ChunkData; using Obsidian.Nbt; using Obsidian.Utilities.Collections; @@ -183,17 +184,17 @@ private static Chunk DeserializeChunk(NbtCompound chunkCompound) if (statesCompound!.TryGetTag("palette", out var palleteArrayTag)) { var blockStatesPalette = palleteArrayTag as NbtList; - foreach (NbtCompound entry in blockStatesPalette!) + foreach (NbtCompound entry in blockStatesPalette!.Cast()) { var id = entry.GetInt("Id"); chunkSecPalette.GetOrAddId(BlocksRegistry.Get(id));//TODO PROCESS ADDED PROPERTIES TO GET CORRECT BLOCK STATE } - - section.BlockStateContainer.GrowDataArray(); } if (statesCompound.TryGetTag("data", out var dataArrayTag)) { + section.BlockStateContainer.InitializeDataArray(); + var data = dataArrayTag as NbtArray; section.BlockStateContainer.DataArray.storage = data!.GetArray(); } @@ -207,12 +208,12 @@ private static Chunk DeserializeChunk(NbtCompound chunkCompound) if (Enum.TryParse(biome.Value.TrimResourceTag(), true, out var value)) biomePalette.GetOrAddId(value); } - - section.BiomeContainer.GrowDataArray(); } if (biomesCompound.TryGetTag("data", out var biomeDataArrayTag)) { + section.BiomeContainer.InitializeDataArray(); + var data = biomeDataArrayTag as NbtArray; section.BiomeContainer.DataArray.storage = data!.GetArray(); } @@ -285,7 +286,8 @@ private static void SerializeChunk(NbtWriterStream writer, IChunk chunk) writer.EndList(); - writer.WriteArray("data", section.BlockStateContainer.DataArray.storage); + if (section.BlockStateContainer.DataArray is not null) + writer.WriteArray("data", section.BlockStateContainer.DataArray.storage); } writer.EndCompound(); @@ -305,7 +307,7 @@ private static void SerializeChunk(NbtWriterStream writer, IChunk chunk) writer.EndList(); - if (indirectBiomePalette.Values.Length > 1) + if (section.BiomeContainer.DataArray is not null) writer.WriteArray("data", section.BiomeContainer.DataArray.storage); } From acdac62f0c6b611b44d092fc88679b89875f7f07 Mon Sep 17 00:00:00 2001 From: Junior Ortiz Cabrera Date: Sat, 27 Sep 2025 12:09:22 -0500 Subject: [PATCH 2/5] Cleanup --- Obsidian.API/ChunkData/DataContainer.cs | 2 +- Obsidian/ChunkData/BlockStateContainer.cs | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Obsidian.API/ChunkData/DataContainer.cs b/Obsidian.API/ChunkData/DataContainer.cs index b5ca0bfed..a99dd68fb 100644 --- a/Obsidian.API/ChunkData/DataContainer.cs +++ b/Obsidian.API/ChunkData/DataContainer.cs @@ -14,7 +14,7 @@ public abstract class DataContainer public abstract IPalette Palette { get; internal set; } - internal virtual DataArray DataArray { get; private protected set; } + internal virtual DataArray? DataArray { get; private protected set; } public virtual int GetIndex(int x, int y, int z) => (y << this.BitsPerEntry | z) << this.BitsPerEntry | x; diff --git a/Obsidian/ChunkData/BlockStateContainer.cs b/Obsidian/ChunkData/BlockStateContainer.cs index b57640bfb..4b8a4c215 100644 --- a/Obsidian/ChunkData/BlockStateContainer.cs +++ b/Obsidian/ChunkData/BlockStateContainer.cs @@ -27,15 +27,6 @@ public override void WriteTo(INetStreamWriter writer) writer.WriteLongArray(DataArray.storage); } - public void Fill(IBlock block) - { - int index = Palette.GetOrAddId(block); - for (int i = 0; i < 16 * 16 * 16; i++) - { - DataArray[i] = index; - } - } - private short GetNonAirBlocks() { int validBlocksCount = 0; From e5b03749e4283beb262cd3dc01b1436b29441ec8 Mon Sep 17 00:00:00 2001 From: Junior Ortiz Cabrera Date: Mon, 29 Sep 2025 17:09:54 -0500 Subject: [PATCH 3/5] Comment out unused heightmaps --- Obsidian.API/_Enums/HeightmapType.cs | 6 ++-- Obsidian/ChunkData/BlockStateContainer.cs | 13 ++++---- Obsidian/WorldData/Chunk.cs | 30 ++----------------- .../Generators/Overworld/ChunkBuilder.cs | 4 +-- Obsidian/WorldData/World.cs | 3 +- 5 files changed, 16 insertions(+), 40 deletions(-) diff --git a/Obsidian.API/_Enums/HeightmapType.cs b/Obsidian.API/_Enums/HeightmapType.cs index ec03d9d50..ef5ff3204 100644 --- a/Obsidian.API/_Enums/HeightmapType.cs +++ b/Obsidian.API/_Enums/HeightmapType.cs @@ -4,9 +4,9 @@ public enum HeightmapType : int WorldSurfaceWG, WorldSurface, - OceanFloorWG, - OceanFloor, + //OceanFloorWG, + //OceanFloor, MotionBlocking, - MotionBlockingNoLeaves, + //MotionBlockingNoLeaves, } diff --git a/Obsidian/ChunkData/BlockStateContainer.cs b/Obsidian/ChunkData/BlockStateContainer.cs index 4b8a4c215..9dfd86152 100644 --- a/Obsidian/ChunkData/BlockStateContainer.cs +++ b/Obsidian/ChunkData/BlockStateContainer.cs @@ -2,13 +2,14 @@ public sealed class BlockStateContainer : DataContainer { + private const int MaxEntryCount = 4096; public override IPalette Palette { get; internal set; } - public override bool IsEmpty => DataArray.storage.Length == 0; + public override bool IsEmpty => this.Palette.Count == 0; - internal BlockStateContainer(byte bitsPerEntry = 0) : base(4096, bitsPerEntry.DetermineBlockPalette(), BlocksRegistry.Air) { } + internal BlockStateContainer(byte bitsPerEntry = 0) : base(MaxEntryCount, bitsPerEntry.DetermineBlockPalette(), BlocksRegistry.Air) { } - private BlockStateContainer(IPalette palette, DataArray dataArray) : base(4096, palette) + private BlockStateContainer(IPalette palette, DataArray dataArray) : base(MaxEntryCount, palette) { Palette = palette; DataArray = dataArray; @@ -39,7 +40,7 @@ private short GetNonAirBlocks() goto TWO_INDEXES; // 1 1 1 - for (int i = 0; i < 16 * 16 * 16; i++) + for (int i = 0; i < MaxEntryCount; i++) { int index = DataArray[i]; if (index != indexOne && index != indexTwo && index != indexThree) @@ -69,7 +70,7 @@ private short GetNonAirBlocks() // 1 0 0 ONE_INDEX: - for (int i = 0; i < 16 * 16 * 16; i++) + for (int i = 0; i < MaxEntryCount; i++) { int index = DataArray[i]; if (index != indexOne) @@ -79,7 +80,7 @@ private short GetNonAirBlocks() // 1 1 0 TWO_INDEXES: - for (int i = 0; i < 16 * 16 * 16; i++) + for (int i = 0; i < MaxEntryCount; i++) { int index = DataArray[i]; if (index != indexOne && index != indexTwo) diff --git a/Obsidian/WorldData/Chunk.cs b/Obsidian/WorldData/Chunk.cs index 4f4863470..129b4bc42 100644 --- a/Obsidian/WorldData/Chunk.cs +++ b/Obsidian/WorldData/Chunk.cs @@ -12,10 +12,6 @@ public sealed class Chunk : IChunk public ChunkGenStage ChunkStatus { get; private set; } = ChunkGenStage.empty; - private const int width = 16; - private const int worldHeight = 320; - private const int worldFloor = -64; - //TODO try and do some temp caching public Dictionary BlockMetaStore { get; private set; } = new Dictionary(); public Dictionary BlockEntities { get; private set; } = new Dictionary(); @@ -31,10 +27,10 @@ public Chunk(int x, int z, ChunkGenStage status = ChunkGenStage.empty) Heightmaps = new Dictionary() { { HeightmapType.MotionBlocking, new Heightmap(HeightmapType.MotionBlocking, this) }, - { HeightmapType.OceanFloor, new Heightmap(HeightmapType.OceanFloor, this) }, - { HeightmapType.WorldSurface, new Heightmap(HeightmapType.WorldSurface, this) }, + //{ HeightmapType.OceanFloor, new Heightmap(HeightmapType.OceanFloor, this) }, + //{ HeightmapType.WorldSurface, new Heightmap(HeightmapType.WorldSurface, this) }, { HeightmapType.WorldSurfaceWG, new Heightmap(HeightmapType.WorldSurfaceWG, this) }, - { HeightmapType.MotionBlockingNoLeaves, new Heightmap(HeightmapType.MotionBlockingNoLeaves, this) } + //{ HeightmapType.MotionBlockingNoLeaves, new Heightmap(HeightmapType.MotionBlockingNoLeaves, this) } }; Sections = new ChunkSection[24]; @@ -155,26 +151,6 @@ public int GetLightLevel(int x, int y, int z, LightType lt) return sec.GetLightLevel(x, y, z, lt); } - public void CalculateHeightmap() - { - Heightmap target = Heightmaps[HeightmapType.MotionBlocking]; - for (int x = 0; x < width; x++) - { - for (int z = 0; z < width; z++) - { - for (int y = worldHeight - 1; y >= worldFloor; y--) - { - var block = GetBlock(x, y, z); - if (block.Material == Material.Air) - continue; - - target.Set(x, z, value: y); - break; - } - } - } - } - public void WriteLightMaskTo(INetStreamWriter writer, LightType lt) { /* diff --git a/Obsidian/WorldData/Generators/Overworld/ChunkBuilder.cs b/Obsidian/WorldData/Generators/Overworld/ChunkBuilder.cs index af2e69e78..29c58e151 100644 --- a/Obsidian/WorldData/Generators/Overworld/ChunkBuilder.cs +++ b/Obsidian/WorldData/Generators/Overworld/ChunkBuilder.cs @@ -284,7 +284,7 @@ internal static void Heightmaps(IChunk chunk) bool worldSurfaceSet = false; bool motionBlockingSet = false; bool motionBlockingLeavesSet = false; - chunk.Heightmaps[HeightmapType.OceanFloor] = chunk.Heightmaps[HeightmapType.WorldSurfaceWG]; + //chunk.Heightmaps[HeightmapType.OceanFloor] = chunk.Heightmaps[HeightmapType.WorldSurfaceWG]; for (int y = 319; y >= -64; y--) { @@ -323,7 +323,7 @@ internal static void Heightmaps(IChunk chunk) !TagsRegistry.Block.Leaves.Entries.Contains(b.RegistryId) ) { - chunk.Heightmaps[HeightmapType.MotionBlockingNoLeaves].Set(x, z, y); + //chunk.Heightmaps[HeightmapType.MotionBlockingNoLeaves].Set(x, z, y); motionBlockingLeavesSet = true; } diff --git a/Obsidian/WorldData/World.cs b/Obsidian/WorldData/World.cs index d7df93939..3a7e4a5f9 100644 --- a/Obsidian/WorldData/World.cs +++ b/Obsidian/WorldData/World.cs @@ -178,8 +178,7 @@ public ValueTask DestroyEntityAsync(IEntity entity) public async ValueTask GetWorldSurfaceHeightAsync(int x, int z) { var c = await GetChunkAsync(x.ToChunkCoord(), z.ToChunkCoord(), false); - return c?.Heightmaps[HeightmapType.WorldSurface] - .GetHeight(NumericsHelper.Modulo(x, 16), NumericsHelper.Modulo(z, 16)); + return c?.Heightmaps[HeightmapType.WorldSurface].GetHeight(NumericsHelper.Modulo(x, 16), NumericsHelper.Modulo(z, 16)); } public async ValueTask SetBlockAsync(int x, int y, int z, IBlock block) From 3ae5526e3daf20c62802c2e542e0db7781bf1ec3 Mon Sep 17 00:00:00 2001 From: Junior Ortiz Cabrera Date: Mon, 29 Sep 2025 17:09:58 -0500 Subject: [PATCH 4/5] Update LevelChunkWithLightPacket.cs --- .../Clientbound/LevelChunkWithLightPacket.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs b/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs index e23e6c27a..ad0bdd596 100644 --- a/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs +++ b/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs @@ -11,22 +11,13 @@ public override void Serialize(INetStreamWriter writer) writer.WriteInt(Chunk.X); writer.WriteInt(Chunk.Z); - //Chunk.CalculateHeightmap(); - + //Heightmap writing we're only sending motion blocking for now. writer.WriteVarInt(1); - foreach (var (type, heightmap) in Chunk.Heightmaps) - if (type == HeightmapType.MotionBlocking) - { - var dataArray = heightmap.GetDataArray(); - - writer.WriteVarInt(type.GetHashCode()); - writer.WriteVarInt(dataArray.Length); + var heightmap = Chunk.Heightmaps[HeightmapType.MotionBlocking]; + var heightmapStorage = heightmap.GetDataArray(); - foreach(var height in dataArray) - writer.WriteLong(height); - - break; - } + writer.WriteVarInt(HeightmapType.MotionBlocking.GetHashCode()); + writer.WriteLengthPrefixedArray(writer.WriteLong, heightmapStorage); var sectionBuffer = new NetworkBuffer(); From cd8649cb4d69f44e710ffb33880fe22b9bfd2843 Mon Sep 17 00:00:00 2001 From: Junior Ortiz Cabrera Date: Mon, 29 Sep 2025 17:17:28 -0500 Subject: [PATCH 5/5] Oopsie --- .../Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs | 2 +- Obsidian/WorldData/Chunk.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs b/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs index ad0bdd596..2271b94c7 100644 --- a/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs +++ b/Obsidian/Net/Packets/Play/Clientbound/LevelChunkWithLightPacket.cs @@ -30,7 +30,7 @@ public override void Serialize(INetStreamWriter writer) } } - writer.WriteVarInt((int)sectionBuffer.Size); + writer.WriteVarInt(sectionBuffer.Size); writer.Write(sectionBuffer); diff --git a/Obsidian/WorldData/Chunk.cs b/Obsidian/WorldData/Chunk.cs index 129b4bc42..a8e6cb7e1 100644 --- a/Obsidian/WorldData/Chunk.cs +++ b/Obsidian/WorldData/Chunk.cs @@ -28,7 +28,7 @@ public Chunk(int x, int z, ChunkGenStage status = ChunkGenStage.empty) { { HeightmapType.MotionBlocking, new Heightmap(HeightmapType.MotionBlocking, this) }, //{ HeightmapType.OceanFloor, new Heightmap(HeightmapType.OceanFloor, this) }, - //{ HeightmapType.WorldSurface, new Heightmap(HeightmapType.WorldSurface, this) }, + { HeightmapType.WorldSurface, new Heightmap(HeightmapType.WorldSurface, this) }, { HeightmapType.WorldSurfaceWG, new Heightmap(HeightmapType.WorldSurfaceWG, this) }, //{ HeightmapType.MotionBlockingNoLeaves, new Heightmap(HeightmapType.MotionBlockingNoLeaves, this) } };