diff --git a/MinecraftClient/Mapping/Chunk.cs b/MinecraftClient/Mapping/Chunk.cs
index 66039f43..89991bfd 100644
--- a/MinecraftClient/Mapping/Chunk.cs
+++ b/MinecraftClient/Mapping/Chunk.cs
@@ -19,7 +19,17 @@ namespace MinecraftClient.Mapping
///
/// Blocks contained into the chunk
///
- private readonly Block[,,] blocks = new Block[SizeX, SizeY, SizeZ];
+ private readonly Block[] blocks;
+
+ public Chunk()
+ {
+ this.blocks = new Block[SizeY * SizeZ * SizeX];
+ }
+
+ public Chunk(Block[] blocks)
+ {
+ this.blocks = blocks;
+ }
///
/// Read, or set the specified block
@@ -39,7 +49,7 @@ namespace MinecraftClient.Mapping
if (blockZ < 0 || blockZ >= SizeZ)
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
- return blocks[blockY, blockZ, blockX];
+ return blocks[(blockY << 8) | (blockZ << 4) | blockX];
}
set
{
@@ -50,7 +60,7 @@ namespace MinecraftClient.Mapping
if (blockZ < 0 || blockZ >= SizeZ)
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
- blocks[blockY, blockZ, blockX] = value;
+ blocks[(blockY << 8) | (blockZ << 4) | blockX] = value;
}
}
@@ -64,7 +74,7 @@ namespace MinecraftClient.Mapping
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void SetWithoutCheck(int blockX, int blockY, int blockZ, Block block)
{
- blocks[blockY, blockZ, blockX] = block;
+ blocks[(blockY << 8) | (blockZ << 4) | blockX] = block;
}
///
diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs
index 2ca27533..a352757c 100644
--- a/MinecraftClient/Protocol/Handlers/DataTypes.cs
+++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs
@@ -46,6 +46,12 @@ namespace MinecraftClient.Protocol.Handlers
return result;
}
+ ///
+ /// Read some data from a cache of bytes and remove it from the cache
+ ///
+ /// Cache of bytes to read from
+ /// Storage results
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void ReadDataReverse(Queue cache, Span dest)
{
for (int i = (dest.Length - 1); i >= 0; --i)
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs
index 84e2fe93..8685ecea 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs
@@ -86,9 +86,10 @@ namespace MinecraftClient.Protocol.Handlers
//// Block IDs are packed in the array of 64-bits integers
dataTypes.SkipNextVarInt(cache);
Span entryDataByte = stackalloc byte[8];
+ Span entryDataLong = MemoryMarshal.Cast(entryDataByte);
dataTypes.ReadDataReverse(cache, entryDataByte); // read long
- Chunk chunk = new();
+ Block[] blocks = new Block[Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ];
int startOffset = 0 - bitsPerEntry;
for (int blockY = 0; blockY < Chunk.SizeY; blockY++)
{
@@ -112,7 +113,7 @@ namespace MinecraftClient.Protocol.Handlers
// NOTICE: In the future a single ushort may not store the entire block id;
// the Block class may need to change if block state IDs go beyond 65535
- ushort blockId = (ushort)((MemoryMarshal.Read(entryDataByte) >> startOffset) & valueMask);
+ uint blockId = (uint)(entryDataLong[0] >> startOffset) & valueMask;
// Map small IDs to actual larger block IDs
if (usePalette)
@@ -127,15 +128,17 @@ namespace MinecraftClient.Protocol.Handlers
blockNumber));
}
- blockId = (ushort)palette[blockId];
+ blockId = palette[(int)blockId];
}
+ Block block = new((ushort)blockId);
+
// We have our block, save the block into the chunk
- chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(blockId));
+ blocks[(blockY << 8) | (blockZ << 4) | blockX] = block;
}
}
}
- return chunk;
+ return new Chunk(blocks);
}
}