Difference between revisions of "Pocket Minecraft Map Format"

From wiki.vg
Jump to navigation Jump to search
(Starting PE Map Format)
 
m (fix spelling mistake)
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
The PE uses a different format for saved games, a NBT little-endian format.
+
[[Category:Pocket_Minecraft]]
Inside a world save folder exists 3 files:
 
  
* level.dat
+
This article describes the Chunk format used in the Full Chunk Data (0xbf, clientbound).
* entities.dat
 
* chunks.dat
 
  
 +
== Concepts ==
  
Further information can be found on the [http://www.minecraftwiki.net/wiki/Pocket_Edition_Level_Format Minecraft Wiki]
+
* Chunk: a 16×128×16 area, sometimes also called chunk section
  
 +
== Format ==
  
[[Category:Pocket Minecraft]]
+
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] &lt;-&gt; 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 &lt;&lt; 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 &lt;&lt; 4) + x</code> and the integer that you pack inside the value is <code>(current &amp; 0xFFFFFF) | (biomeId &lt;&lt; 24)</code> where <code>current = biomes[(z &lt;&lt; 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 &amp; 0xFF000000) &gt;&gt; 24</code> where <code>current = biomes[(z &lt;&lt; 4) + x]</code>. For setting the r, g, b color of each chunk you can do a similar key <code>[(z &lt;&lt; 4) | x]</code> and unpack the r, g, b by <code>color &gt;&gt; 16, (color &gt;&gt; 8) &amp; 0xFF, color &amp; 0xFF</code> and pack it again by getting the correct color <code>(biome[(z &lt;&lt; 4) + x] &amp; 0xFF000000) | ((R &amp; 0xFF) &lt;&lt; 16) | ((G &amp; 0xFF) &lt;&lt; 8) | (B &amp; 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).

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 and Z 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

Sources