Difference between revisions of "Pocket Minecraft Map Format"
(Starting PE Map Format) |
m (fix spelling mistake) |
||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | + | [[Category:Pocket_Minecraft]] | |
− | |||
− | + | This article describes the Chunk format used in the Full Chunk Data (0xbf, clientbound). | |
− | |||
− | |||
+ | == Concepts == | ||
− | + | * Chunk: a 16×128×16 area, sometimes also called chunk section | |
+ | == Format == | ||
− | [[ | + | A chunk consists of the following fields (fixed size of 83200 bytes): |
+ | |||
+ | {| class="wikitable" | ||
+ | ! Field Name | ||
+ | ! Field Type | ||
+ | ! Notes | ||
+ | |- | ||
+ | | Blocks | ||
+ | | Array of bytes | ||
+ | | Always a size of 32,768 bytes | ||
+ | |- | ||
+ | | Regular Data | ||
+ | | Array of bytes | ||
+ | | Always a size of 16,384 bytes | ||
+ | |- | ||
+ | | Sky Light | ||
+ | | Array of bytes | ||
+ | | Always a size of 16,384 bytes, half byte per block | ||
+ | |- | ||
+ | | Block Light | ||
+ | | Array of bytes | ||
+ | | Always a size of 16,384 bytes, half byte per block | ||
+ | |- | ||
+ | | Height Map | ||
+ | | Array of ints | ||
+ | | Always a size of 256 bytes | ||
+ | |- | ||
+ | | Biome Colors | ||
+ | | Array of ints | ||
+ | | Always a size of 1024 bytes | ||
+ | |} | ||
+ | |||
+ | === Blocks === | ||
+ | |||
+ | The following definitions are provided to clarify the mapping between the location of a block within a LevelDB entry containing a chunk of 32,768 blocks and the corresponding location of the block within the entire world: | ||
+ | |||
+ | * Let <code>X</code> and <code>Z</code> be the values contained within the LevelDB key. | ||
+ | * Let <code>C[]</code> be a three dimensional array of the chunk of 32,768 blocks contained within the LevelDB entry. The first two indices i and j range from 0 to 15, and the third index y ranges from 0 to 127. | ||
+ | * Let <code>W[]</code> be a three dimensional array of the blocks contained within the entire world. | ||
+ | |||
+ | For infinite worlds, the first two indices <code>x</code> and <code>z</code> both range over the values of a four byte integer and may be negative as well as positive. | ||
+ | |||
+ | The third index <code>y</code> ranges from 0 to 127 for both old style and infinite worlds. | ||
+ | |||
+ | Assuming the definitions above, the location of a block with a LevelDB entry with key values <code>X</code> and <code>Z</code> maps to the corresponding location of the block within the entire world as follows: | ||
+ | |||
+ | <pre>let x = 16 * X + i | ||
+ | let z = 16 * Z + j | ||
+ | C[i, j, y] <-> W[x, z, y]</pre> | ||
+ | === Skylight/Blocklight/Metadata === | ||
+ | |||
+ | Block light and skylight are very similar to the 1.8 implementation used in the Minecraft: PC edition of the game. All chunks always have the same value and have a fixed size of 83200, you can index the skylight/blocklight/metadata by block by using <code>(x * 2048) + (z * 128) + y</code> where x, y, z are the coordinates of the block you are trying to retrieve the skylight/blocklight/metadata for. | ||
+ | |||
+ | === Heightmap === | ||
+ | |||
+ | The heightmap is the mapping between the height of each block in a chunk for retrieveing by x and z you can simply <code>(z << 4) + x</code> to get the value or set it. | ||
+ | |||
+ | === Biome colors === | ||
+ | |||
+ | Each block in a single column has a biome id and (unlike the PC version of the game) an r, g, b value associated with it that is used for the client to render the color (more like hue) of the block. For finding/setting the biome id for a column of blocks the key for each column is <code>(z << 4) + x</code> and the integer that you pack inside the value is <code>(current & 0xFFFFFF) | (biomeId << 24)</code> where <code>current = biomes[(z << 4) + x]</code> and <code>biomeId = the id of the biome</code> for getting the id, it is the same but you just reverse it <code>(current & 0xFF000000) >> 24</code> where <code>current = biomes[(z << 4) + x]</code>. For setting the r, g, b color of each chunk you can do a similar key <code>[(z << 4) | x]</code> and unpack the r, g, b by <code>color >> 16, (color >> 8) & 0xFF, color & 0xFF</code> and pack it again by getting the correct color <code>(biome[(z << 4) + x] & 0xFF000000) | ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0XFF)</code>. | ||
+ | |||
+ | == LevelDB == | ||
+ | |||
+ | In the Minecraft: PE application, all chunks are stored in Mojang’s fork of LevelDB (a ZLib compressed LevelDB database) each key follows the same format unless you are using a special key, or a nether key | ||
+ | |||
+ | For an overworld key, it is quite trivial (always 9 bytes long): | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Field Name | ||
+ | ! Field Type | ||
+ | |- | ||
+ | | X Coordinate | ||
+ | | Little-endian int | ||
+ | |- | ||
+ | | Z Coordinate | ||
+ | | Little-endian int | ||
+ | |- | ||
+ | | Type | ||
+ | | A byte containing the type of data, see bytes below | ||
+ | |} | ||
+ | |||
+ | For a nether key it is similar, but with an extra byte after Z Coordinate (always 13 bytes long): | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Field Name | ||
+ | ! Field Type | ||
+ | |- | ||
+ | | X Coordinate | ||
+ | | Little-endian int | ||
+ | |- | ||
+ | | Z Coordinate | ||
+ | | Little-endian int | ||
+ | |- | ||
+ | | Nether specifier | ||
+ | | Little-endian int, always a value of 1 | ||
+ | |- | ||
+ | | Type | ||
+ | | A byte containing the type of data, see bytes below | ||
+ | |} | ||
+ | |||
+ | The corresponding byte specifier for the type of chunk are: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! Field Name | ||
+ | ! Field Value | ||
+ | |- | ||
+ | | Terrain Data | ||
+ | | 0x30 (48 in decimal, ‘0’ ASCII) | ||
+ | |- | ||
+ | | Tile Entity Data | ||
+ | | 0x31 (49 in decimal, ‘1’ ASCII) | ||
+ | |- | ||
+ | | Entity Data | ||
+ | | 0x32 (50 in decimal, ‘2’ ASCII) | ||
+ | |- | ||
+ | | 1-byte Data | ||
+ | | 0x76 (118 in decimal, ‘v’ ASCII) | ||
+ | |} | ||
+ | |||
+ | Tile Entity Data and Entity Data are encoded as NBT, the format of Terrain Data is specified above. | ||
+ | |||
+ | == Implementations == | ||
+ | |||
+ | * Mojang’s LevelDB: https://github.com/Mojang/leveldb-mcpe | ||
+ | |||
+ | == Sources == | ||
+ | |||
+ | * http://minecraft.gamepedia.com/Pocket_Edition_level_format | ||
+ | * https://github.com/Nukkit/Nukkit/blob/master/src/main/java/cn/nukkit/level/format/generic/BaseFullChunk.java | ||
+ | * https://github.com/NiclasOlofsson/MiNET/blob/master/src/MiNET/MiNET/Worlds/ChunkColumn.cs |
Latest revision as of 21:16, 26 May 2016
This article describes the Chunk format used in the Full Chunk Data (0xbf, clientbound).
Contents
Concepts
- Chunk: a 16×128×16 area, sometimes also called chunk section
Format
A chunk consists of the following fields (fixed size of 83200 bytes):
Field Name | Field Type | Notes |
---|---|---|
Blocks | Array of bytes | Always a size of 32,768 bytes |
Regular Data | Array of bytes | Always a size of 16,384 bytes |
Sky Light | Array of bytes | Always a size of 16,384 bytes, half byte per block |
Block Light | Array of bytes | Always a size of 16,384 bytes, half byte per block |
Height Map | Array of ints | Always a size of 256 bytes |
Biome Colors | Array of ints | Always a size of 1024 bytes |
Blocks
The following definitions are provided to clarify the mapping between the location of a block within a LevelDB entry containing a chunk of 32,768 blocks and the corresponding location of the block within the entire world:
- Let
X
andZ
be the values contained within the LevelDB key. - Let
C[]
be a three dimensional array of the chunk of 32,768 blocks contained within the LevelDB entry. The first two indices i and j range from 0 to 15, and the third index y ranges from 0 to 127. - Let
W[]
be a three dimensional array of the blocks contained within the entire world.
For infinite worlds, the first two indices x
and z
both range over the values of a four byte integer and may be negative as well as positive.
The third index y
ranges from 0 to 127 for both old style and infinite worlds.
Assuming the definitions above, the location of a block with a LevelDB entry with key values X
and Z
maps to the corresponding location of the block within the entire world as follows:
let x = 16 * X + i let z = 16 * Z + j C[i, j, y] <-> W[x, z, y]
Skylight/Blocklight/Metadata
Block light and skylight are very similar to the 1.8 implementation used in the Minecraft: PC edition of the game. All chunks always have the same value and have a fixed size of 83200, you can index the skylight/blocklight/metadata by block by using (x * 2048) + (z * 128) + y
where x, y, z are the coordinates of the block you are trying to retrieve the skylight/blocklight/metadata for.
Heightmap
The heightmap is the mapping between the height of each block in a chunk for retrieveing by x and z you can simply (z << 4) + x
to get the value or set it.
Biome colors
Each block in a single column has a biome id and (unlike the PC version of the game) an r, g, b value associated with it that is used for the client to render the color (more like hue) of the block. For finding/setting the biome id for a column of blocks the key for each column is (z << 4) + x
and the integer that you pack inside the value is (current & 0xFFFFFF) | (biomeId << 24)
where current = biomes[(z << 4) + x]
and biomeId = the id of the biome
for getting the id, it is the same but you just reverse it (current & 0xFF000000) >> 24
where current = biomes[(z << 4) + x]
. For setting the r, g, b color of each chunk you can do a similar key [(z << 4) | x]
and unpack the r, g, b by color >> 16, (color >> 8) & 0xFF, color & 0xFF
and pack it again by getting the correct color (biome[(z << 4) + x] & 0xFF000000) | ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0XFF)
.
LevelDB
In the Minecraft: PE application, all chunks are stored in Mojang’s fork of LevelDB (a ZLib compressed LevelDB database) each key follows the same format unless you are using a special key, or a nether key
For an overworld key, it is quite trivial (always 9 bytes long):
Field Name | Field Type |
---|---|
X Coordinate | Little-endian int |
Z Coordinate | Little-endian int |
Type | A byte containing the type of data, see bytes below |
For a nether key it is similar, but with an extra byte after Z Coordinate (always 13 bytes long):
Field Name | Field Type |
---|---|
X Coordinate | Little-endian int |
Z Coordinate | Little-endian int |
Nether specifier | Little-endian int, always a value of 1 |
Type | A byte containing the type of data, see bytes below |
The corresponding byte specifier for the type of chunk are:
Field Name | Field Value |
---|---|
Terrain Data | 0x30 (48 in decimal, ‘0’ ASCII) |
Tile Entity Data | 0x31 (49 in decimal, ‘1’ ASCII) |
Entity Data | 0x32 (50 in decimal, ‘2’ ASCII) |
1-byte Data | 0x76 (118 in decimal, ‘v’ ASCII) |
Tile Entity Data and Entity Data are encoded as NBT, the format of Terrain Data is specified above.
Implementations
- Mojang’s LevelDB: https://github.com/Mojang/leveldb-mcpe