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>
/// Blocks contained into the chunk
/// </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>
/// 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;
}
/// <summary>

View file

@ -46,6 +46,12 @@ namespace MinecraftClient.Protocol.Handlers
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)
{
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
dataTypes.SkipNextVarInt(cache);
Span<byte> entryDataByte = stackalloc byte[8];
Span<long> entryDataLong = MemoryMarshal.Cast<byte, long>(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<long>(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);
}
}