diff --git a/MinecraftClient/Mapping/ChunkColumn.cs b/MinecraftClient/Mapping/ChunkColumn.cs index ca828712..5e40c954 100644 --- a/MinecraftClient/Mapping/ChunkColumn.cs +++ b/MinecraftClient/Mapping/ChunkColumn.cs @@ -18,7 +18,7 @@ namespace MinecraftClient.Mapping /// /// Blocks contained into the chunk /// - private readonly Chunk[] chunks; + private readonly Chunk?[] chunks; /// /// Create a new ChunkColumn @@ -26,7 +26,7 @@ namespace MinecraftClient.Mapping public ChunkColumn(int size = 16) { ColumnSize = size; - chunks = new Chunk[size]; + chunks = new Chunk?[size]; } /// @@ -35,7 +35,7 @@ namespace MinecraftClient.Mapping /// ChunkColumn X /// ChunkColumn Y /// chunk at the given location - public Chunk this[int chunkY] + public Chunk? this[int chunkY] { get { diff --git a/MinecraftClient/Mapping/World.cs b/MinecraftClient/Mapping/World.cs index 5810d2cc..f272ead8 100644 --- a/MinecraftClient/Mapping/World.cs +++ b/MinecraftClient/Mapping/World.cs @@ -118,10 +118,9 @@ namespace MinecraftClient.Mapping /// ChunkColumn size /// Chunk data /// Whether the ChunkColumn has been fully loaded - public void StoreChunk(int chunkX, int chunkY, int chunkZ, int chunkColumnSize, Chunk chunk, bool loadCompleted) + public void StoreChunk(int chunkX, int chunkY, int chunkZ, int chunkColumnSize, Chunk? chunk, bool loadCompleted) { ChunkColumn? chunkColumn = null; - chunksLock.EnterUpgradeableReadLock(); try { @@ -151,7 +150,6 @@ namespace MinecraftClient.Mapping { chunksLock.ExitUpgradeableReadLock(); } - chunkColumn[chunkY] = chunk; if (loadCompleted) chunkColumn.FullyLoaded = true; diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs index da6fa533..e1283daa 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Numerics; using System.Threading; +using System.Threading.Tasks; //using System.Linq; //using System.Text; using MinecraftClient.Mapping; @@ -32,9 +33,8 @@ namespace MinecraftClient.Protocol.Handlers /// /// Reading the "Block states" field: consists of 4096 entries, representing all the blocks in the chunk section. /// - /// Blocks will store in this chunk /// Cache for reading data - private Chunk? ReadBlockStatesField(ref Chunk chunk, Queue cache) + private Chunk? ReadBlockStatesField(Queue cache) { // read Block states (Type: Paletted Container) byte bitsPerEntry = dataTypes.ReadNextByte(cache); @@ -44,18 +44,20 @@ namespace MinecraftClient.Protocol.Handlers { // Palettes: Single valued - 1.18(1.18.1) and above ushort blockId = (ushort)dataTypes.ReadNextVarInt(cache); + Block block = new(blockId); dataTypes.SkipNextVarInt(cache); // Data Array Length will be zero // Empty chunks will not be stored - if (new Block(blockId).Type == Material.Air) + if (block.Type == Material.Air) return null; + Chunk chunk = new(); for (int blockY = 0; blockY < Chunk.SizeY; blockY++) for (int blockZ = 0; blockZ < Chunk.SizeZ; blockZ++) for (int blockX = 0; blockX < Chunk.SizeX; blockX++) - chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(blockId)); - + chunk.SetWithoutCheck(blockX, blockY, blockZ, block); + return chunk; } else { @@ -79,6 +81,7 @@ namespace MinecraftClient.Protocol.Handlers // Block IDs are packed in the array of 64-bits integers ulong[] dataArray = dataTypes.ReadNextULongArray(cache); + Chunk chunk = new(); int longIndex = 0; int startOffset = 0 - bitsPerEntry; for (int blockY = 0; blockY < Chunk.SizeY; blockY++) @@ -87,10 +90,6 @@ namespace MinecraftClient.Protocol.Handlers { for (int blockX = 0; blockX < Chunk.SizeX; blockX++) { - // 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; - // Calculate location of next block ID inside the array of Longs startOffset += bitsPerEntry; @@ -105,8 +104,9 @@ namespace MinecraftClient.Protocol.Handlers longIndex++; } - // Extract Block ID - blockId = (ushort)((dataArray[longIndex] >> startOffset) & valueMask); + // 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)((dataArray[longIndex] >> startOffset) & valueMask); // Map small IDs to actual larger block IDs if (usePalette) @@ -129,9 +129,8 @@ namespace MinecraftClient.Protocol.Handlers } } } + return chunk; } - - return chunk; } /// @@ -156,11 +155,13 @@ namespace MinecraftClient.Protocol.Handlers { // 1.17 and above chunk format // Unloading chunks is handled by a separate packet + for (int chunkY = 0; chunkY < chunkColumnSize; chunkY++) { - int lastChunkY = 0; + int lastChunkY; if (protocolversion == Protocol18Handler.MC_1_17_Version || protocolversion == Protocol18Handler.MC_1_17_1_Version) { + lastChunkY = 0; for (int i = verticalStripBitmask!.Length - 1; i >= 0; --i) { if (verticalStripBitmask![i] != 0) @@ -187,8 +188,7 @@ namespace MinecraftClient.Protocol.Handlers int blockCnt = dataTypes.ReadNextShort(cache); // Read Block states (Type: Paletted Container) - Chunk chunk = new Chunk(); - ReadBlockStatesField(ref chunk, cache); + Chunk? chunk = ReadBlockStatesField(cache); // check before store chunk if (cancellationToken.IsCancellationRequested)