Many chunk sections contain parts of their data that are the same for
every block they contain. In these cases we can save memory by saving
a single value instead of an array of 4096 copies of that value. Block light
and block data are most likely to be uniform followed closely by sky light
data. Block ids are far less likely to be uniform but give the largest
saving when they are. Because of this we use a compact format for every
part of the chunk. Memory saved from this technique will vary based on the
world but seems to be about 50% on normal Minecraft generated chunks.
If a chunk has somehow managed to save with arrays that are not 4096
entries long when reading them again we will get exceptions. Checking the
array length and resizing if needed is cheap so we should do this to help
avoid crashing servers due to this error.
If a chunk gets a block added to it that requires the extended block id
nibble array (block id greater than 255) the array is created and saved
with the chunk. When the blocks are verified to make sure they exist these
entries are erased but the extended block id array is not. This causes the
server and client to disagree about how much data a chunk has which makes
the client crash while trying to load the chunk for rendering.
To resolve these issues we now clear the extended block id array on chunk
load if there is no valid data in it.
ChunkSection.e() is called once per chunk section loaded and is quite
expensive (about 20% of CPU time for loading the chunk). This changes the
logic to add a fast path when extended block data is not being used and
reorganizes the loops for more optimal array traversal. Overall this saves
about 20-30% CPU time in this method.