From e09016cea57cb8c56c6209bcc88f3b773063ada1 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Tue, 30 Aug 2022 12:33:13 +0800 Subject: [PATCH] Improve ReadBlockStatesField --- MinecraftClient/Mapping/Chunk.cs | 18 ++++++++++++++---- MinecraftClient/Protocol/Handlers/DataTypes.cs | 6 ++++++ .../Protocol/Handlers/Protocol18Terrain.cs | 13 ++++++++----- 3 files changed, 28 insertions(+), 9 deletions(-) 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); } }