Elytra-Server / Elytra

A Cleanroom minecraft server API in kotlin
MIT License
51 stars 6 forks source link

Possible chunk data improvements #35

Closed WinX64 closed 4 years ago

WinX64 commented 4 years ago

Contextualization Recent versions of the game have completely revamped the method for storing block information in chunks. Instead of an array directly holding block ids, chunks now utilize a palette mapping mechanism.

Each chunk section is comprised of a block palette and a data array. The palette holds the block state id of each block present in the section, while the array holds the index (in the local palette) of each block in the chunk. As this palette contains considerably less elements than the global palette, less bits are needed to represent the indexes in the data array. The number of bits needed grows with the number of blocks in the chunk section palette, following a rounded-up base 2 log rule.

This technique helps to reduce the size of chunks with a lesser diversity of block types, and by consequence, the amount of data needed to be sent to the client.

The (possible) problem As of now, the game follows some fixed rules on the number of bits needed to encode the palette indexes. The first one is that the minimum size is set to 4, a possible strategy to give a good interval (16 blocks) and avoid needing to constantly recalculate the data array for chunks with few block types.

The second one is that, after a certain number of bits, the game will stop mapping indexes from the local palette, and use the global one instead. This is most likely used to avoid the number of elements growing too much in size due to the large number of bits needed to encode the indexes (along with the data array itself). Currently, the game starts mapping from the global palette at 9 bits, up to 14 (the current maximum).

However, calculations show that it should only start at 11 bits instead. Chunk sections mapped using the Global palette have a constant size of 7168 bytes. If the palette is mapped using the maximum of 8 bits, as in Vanilla, the chunk size will only go up to 4610 bytes before changing to the global palette scheme.

The (possible) solution If we consider 10 bits, however, it will be able to go up to 7120 bytes before changing schemes. Comparison As such, the current suggestion is to utilize 11 as the limit, in order to reduce the final chunk data packet sizes even further. However, tests need to be conducted to verify how the client will behave to this. How will it react upon receiving a chunk data packet with a number of bits set to 9? Will it adjust the data received, or refuse the packet entirely?

In the case that it accepts and adjusts it, other points that need further research include if having de-synced palette configurations between client and server will affect any other aspect. As of now, its confirmed that this won't cause block mismatches, since all block related packets (block change, multi block change, etc.), aside from the chunk data one itself, utilize ids from the global palette.

TommyAlmeida commented 4 years ago

Closed due client now allowing that.