mojira.dev
MCPE-242992

Improper Storage of POI Region Data in LevelDB With Custom Height Limit

On a world with a behavior pack that defines a custom height limit like -512 to 512, if the total height range is greater than 512, the Y coordinate in a POI entry can overflow in the POI region data in the LevelDB.

The POI region data I am referring to in the LevelDB is under LevelDB keys in the format poi.#.regions.#.#.

The data structure is a map with 4-byte keys containing the relative block location within the 512x512 region and 3-byte values consisting of 2 bytes representing the POI type and 1 byte storing the number of tickets.

The integer values of the keys are currently in the format <5 unused bits><9-bit Z coordinate><9-bit Y coordinate><9-bit X coordinate> and encoded in little-endian.

The problem comes from using 9 bits for the Y coordinate instead of 10, a 9-bit integer can only store 512 possible values, but the maximum possible total height range is 1024, a 10-bit integer would allow for storing all 1024 possible Y values.

Here is an example of the issue:

There is a lodestone at 1495 88 102327, its region relative X and Z coordinates are 471 and 439, it is in region 2, 199.
In a normal world the Y coordinate is stored as 010011000, which is 152, and since 88-(-64)=152 this is correct.
But in a world with a -512 to 512 height range, the Y coordinate is stored as 001011000, which is 88, but 88-(-512)=600, not 88, but it gets written as 88 because 600 overflows when trying to store it as a 9-bit integer and ends up as 88.
And if there was another lodestone at 1495 -424 102327, that lodestone would correctly have the Y coordinate stored as 88, but since the lodestone at Y=88 already used that key in the map due to overflowing, now there is a collision, and either the Y=88 or the Y=-424 lodestone gets discarded from the POI region data.
Any two POI entries that are 512 blocks apart on the Y axis currently will collide due to the higher one overflowing to end up with the same coordinate key as the lower one.

Steps to Reproduce:

  1. Create a world and add a behavior pack that sets the overworld height limits to -512 to 512.

  2. Place lodestones at 0, -424, 0 and the other at 0, 88, 0.

  3. View the poi.0.regions.0.0LevelDB key of the world.

  4. Notice that there is only one lodestone POI entry, when there should be 2.

Expected Result:

There should be 2 lodestone POI entries, both with different keys.

Actual Result:

There is only 1 lodestone POI entry, with the key of the Y=-424 lodestone.

Comments 0

No comments.

Andexter

(Unassigned)

Unconfirmed

Multiple

26.51 Hotfix

Retrieved