Improve ReadBlockStatesField

This commit is contained in:
BruceChen 2022-08-30 12:33:13 +08:00
parent cd45c64300
commit e09016cea5
3 changed files with 28 additions and 9 deletions

View file

@ -19,7 +19,17 @@ namespace MinecraftClient.Mapping
/// <summary> /// <summary>
/// Blocks contained into the chunk /// Blocks contained into the chunk
/// </summary> /// </summary>
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;
}
/// <summary> /// <summary>
/// Read, or set the specified block /// Read, or set the specified block
@ -39,7 +49,7 @@ namespace MinecraftClient.Mapping
if (blockZ < 0 || blockZ >= SizeZ) if (blockZ < 0 || blockZ >= SizeZ)
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)"); 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 set
{ {
@ -50,7 +60,7 @@ namespace MinecraftClient.Mapping
if (blockZ < 0 || blockZ >= SizeZ) if (blockZ < 0 || blockZ >= SizeZ)
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)"); 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)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void SetWithoutCheck(int blockX, int blockY, int blockZ, Block block) public void SetWithoutCheck(int blockX, int blockY, int blockZ, Block block)
{ {
blocks[blockY, blockZ, blockX] = block; blocks[(blockY << 8) | (blockZ << 4) | blockX] = block;
} }
/// <summary> /// <summary>

View file

@ -46,6 +46,12 @@ namespace MinecraftClient.Protocol.Handlers
return result; return result;
} }
/// <summary>
/// Read some data from a cache of bytes and remove it from the cache
/// </summary>
/// <param name="cache">Cache of bytes to read from</param>
/// <param name="dest">Storage results</param>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void ReadDataReverse(Queue<byte> cache, Span<byte> dest) public void ReadDataReverse(Queue<byte> cache, Span<byte> dest)
{ {
for (int i = (dest.Length - 1); i >= 0; --i) for (int i = (dest.Length - 1); i >= 0; --i)

View file

@ -86,9 +86,10 @@ namespace MinecraftClient.Protocol.Handlers
//// Block IDs are packed in the array of 64-bits integers //// Block IDs are packed in the array of 64-bits integers
dataTypes.SkipNextVarInt(cache); dataTypes.SkipNextVarInt(cache);
Span<byte> entryDataByte = stackalloc byte[8]; Span<byte> entryDataByte = stackalloc byte[8];
Span<long> entryDataLong = MemoryMarshal.Cast<byte, long>(entryDataByte);
dataTypes.ReadDataReverse(cache, entryDataByte); // read long dataTypes.ReadDataReverse(cache, entryDataByte); // read long
Chunk chunk = new(); Block[] blocks = new Block[Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ];
int startOffset = 0 - bitsPerEntry; int startOffset = 0 - bitsPerEntry;
for (int blockY = 0; blockY < Chunk.SizeY; blockY++) 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; // 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 // the Block class may need to change if block state IDs go beyond 65535
ushort blockId = (ushort)((MemoryMarshal.Read<long>(entryDataByte) >> startOffset) & valueMask); uint blockId = (uint)(entryDataLong[0] >> startOffset) & valueMask;
// Map small IDs to actual larger block IDs // Map small IDs to actual larger block IDs
if (usePalette) if (usePalette)
@ -127,15 +128,17 @@ namespace MinecraftClient.Protocol.Handlers
blockNumber)); blockNumber));
} }
blockId = (ushort)palette[blockId]; blockId = palette[(int)blockId];
} }
Block block = new((ushort)blockId);
// We have our block, save the block into the chunk // 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);
} }
} }