Bedrock Edition level format

Bedrock Edition uses a modified version of Google's LevelDB, which uses the Zlib compression format for level storage.

1.0
1.0 stores each subchunk separately as a different leveldb key.

E.g. The Overworld:

Any other dimension:

The possible tags are these: enum class Tag : char { Data2D = 45, Data2DLegacy = 46, SubChunkPrefix = 47, LegacyTerrain = 48, BlockEntity = 49, Entity = 50, PendingTicks = 51, BlockExtraData = 52, BiomeState = 53, FinalizedState = 54, Version = 118 };

To ask for a specific SubChunk you need to put "47" in the Tag and a number between 0 and 15 in the Subchunk ID. Note that subchunks are allowed to not exist! But they will always work like a stack, eg. if a chunk is there, all chunks below it should also be there.

The SubChunks are formatted like so:


 * Version: 1 byte
 * Block IDs: 4kb, 8 bits per block
 * Block Data: 2kb, 4 bits per block
 * Sky Light: 2kb, 4 bits per block
 * Block Light: 2kb, 4 bits per block

LevelDB format
Mojang's modified LevelDB is available at https://github.com/Mojang/leveldb-mcpe, and the build parameters required to build it are documented by Tommaso at. The Official LevelDB page is at https://code.google.com/p/leveldb/. To read a Bedrock Edition level see here: https://github.com/tinfoiled/leveldb

The database is stored in the db/ subdirectory of a Bedrock Edition world. It seems this is also where terrain generation is stored. This is because you can turn an old world infinite by replacing its db folder with one from an infinite world.

There are three types of data stored in the database: terrain data, entity data, and tile entity data.

Key format: 9 byte key, which seems to consist of:
 * x coordinate of chunk as little endian integer
 * z coordinate of chunk as little endian integer
 * one more byte indicating the type of the data:
 * 0x30 (48 in decimal, '0' ASCII) for what appears to be terrain data
 * 0x31 (49 in decimal, '1' ASCII) for tile entity data
 * 0x32 (50 in decimal, '2' ASCII) for entity data
 * 0x76 (118 in decimal, 'v' ASCII) for 1-byte data

Since the introduction in version 0.12.1 of the Nether, there are also special keys for Nether chunks, which are 13 bytes long, and seem to consist of:
 * x coordinate of chunk as little endian integer
 * z coordinate of chunk as little endian integer
 * 1 as little endian integer (0x01 0x00 0x00 0x00)
 * one more byte indicating the type of the data:
 * 0x30 (48 in decimal, '0' ASCII) for what appears to be terrain data
 * 0x31 (49 in decimal, '1' ASCII) for tile entity data
 * 0x32 (50 in decimal, '2' ASCII) for entity data
 * 0x76 (118 in decimal, 'v' ASCII) for 1-byte data

The 0x30 terrain data entry appears to contain block data for an x*z*y = 16*16*128 block chunk. The value associated with the 0x30 terrain data key is always of length 83,200 and seems to consist of the following data:
 * 32,768 bytes of block data which appears to be a x*z*y = 16*16*128 block chunk.
 * 16,384 bytes of regular data (one nibble for each byte of block data above).
 * 16,384 bytes of skylight data (one nibble for each byte of block data above).
 * 16,384 bytes of block light data (one nibble for each byte of block data above).
 * 256 bytes of additional data which appears to be a z*x = 16*16 byte array (one byte for each vertical y column of 128 bytes of block data above) containing dirty column info.
 * 1,024 bytes of additional data which appears to be a 16*16*4 byte array (four bytes for each vertical y column of 128 bytes of block data above) containing grass color info.

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: 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: The x index specifies the North to South location where a smaller value of x is farther North than a larger value of x. The z index specifies the East to West location where a smaller value of z is farther East than a larger value of z. The y index specifies the vertical location where a smaller value of y is at a lower height than a larger value of y. For an old style world, the block at the bottom of the North-East corner of the world is W [0, 0, 0].
 * 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 old style worlds, the first two indices x and z both range from 0 to 255. 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.
 * C [i, j, y] <->  W [x, z, y] where x = 16*X + i and z = 16*Z + j

The 0x31 tile entity and 0x32 entity data entries above are NBT encoded and may contain 0, 1, or multiple-concatenated Compound tags at the root level. In the case of 0 Compound tags, LevelDB indicates 0 as the length of the value associated with the key. Multiple-concatenated tags are supported because there can be more than one entity per chunk. Every 0x31 tile entity and 0x32 entity entry has an associated 0x30 terrain entry, but an 0x30 terrain entry will not necessarily have an associated 0x31 tile entity or 0x32 entity entry.

The number of 0x30 terrain entries and 0x76 1-byte data entries is always the same, and there is a one-to-one relationship between these entries where the corresponding entries both have the same x and z values. Three values have been observed for the 1-byte data including the binary values 0, 1, and 2. The value 0 has been observed in old style worlds, and the values 1 and 2 have been observed in infinite worlds.

There's also the special key ~local_player for an entity data entry that holds the local player entity. If entity data exists here, it takes precedence over the player data stored in level.dat. The value associated with the ~local_player key is NBT encoded and only has a single compound tag at the root level.

There's also a special key for remote players which consists of two parts. The first part is the prefix "player_" (without the quotes) and the second part is the client ID which is contained in the remote player's clientid.txt file. For example, player_-12345678 would be the key for a remote client with an client ID of -12345678. The value associated with the “player_” prefixed key is NBT encoded and only has a single compound tag at the root level.

There's also a special “game_flatworldlayers” key of length 20 for flat worlds. The value associated with this key is a set of numbers in ASCII text format. An example of a value associated with the “game_flatworldlayers” key is “[7,3,3,2]” where the value length for this example is 9.

Structure

 * World data.
 * : The dimension the player is in. 0 is the Overworld.
 * : Whether in survival (0) or in creative (1) mode.
 * : World Type: Old, Infinite, or Flat
 * : Stores the Unix time stamp (in seconds) when the player saved the game.
 * : Specifies the name of the level.
 * LimitedWorldOrigin. (Only applies to old type worlds)
 * : X coordinate where limited world generation started.
 * : Y coordinate where limited world generation started.
 * : Z coordinate where limited world generation started.
 * : Seems to store the platform that the level is created on. Currently observed value is 2.
 * : Level Seed
 * : Estimated size of level in bytes
 * Spawn Coordinates of world
 * : X coordinate of the player's spawn position. Default is 0.
 * : Y coordinate of the player's spawn position. Default is 64.
 * : Z coordinate of the player's spawn position. Default is 0.
 * :Version of Bedrock Edition Storage Tool, currently is 4
 * : Stores the current "time of day" in ticks. There are 20 ticks per real-life second, and 14400 ticks per Minecraft day/night cycle, making the full cycle length 12 minutes—8 minutes shorter than the standard 20 minute day/night cycle. 0 is the start of daytime, 7200 is the start of sunset, 8280 is the start of nighttime, 13320 is the start of sunrise, and 14400 is daytime again. The value stored in level.dat is always increasing and can be larger than 14400, but the "time of day" is always modulo 14400 of the "Time" field value.
 * : Added in 8.0. Default is 18446744073709552000.
 * : Disable (0) or enable (1) mob spawning.

LOG
The LOG files are located at the /db path of a level, and are part of the leveldb format, used in between compaction of the LDB files. It is similar to a Log file for a program. The format is:

YYYY /MM/DD-Hour/Minute/Second.StepName "Info"

Example:

2014/07/24-22:20:08.400488 4a3638 Recovering log #3

level.dat
The level.dat file is in NBT format, based on the format of level.dat in a Desktop world. level.dat is an uncompressed little-endian NBT file that stores environmental data (time of day, for example) and player health, inventory, velocity, and position within the map.

The file begins with an 8-byte header, consisting of a little-endian 4-byte integer indicating the type of the file, which is 3 (was 2 before latest update) for level.dat. It is followed by another integer containing the length of the file, minus the header.

NBT Structure

 * World data.
 * : Whether in survival (0) or in creative (1) mode.
 * : Stores the Unix time stamp (in seconds) when the player saved the game.
 * : Specifies the name of the level.
 * : Seems to store the platform that the level is created on. Currently observed value is 2.
 * : Player entity information. See Entity Format and Mob Entity Format for details. It is missing the id tag and has additional elements:
 * : Each TAG_Compound in this list defines a piece of armor that the player is wearing. This is a list with length 4 - for helmet, chestplate, leggings, and boots.
 * Inventory item data
 * : Item or Block ID.
 * : Number of items stacked in this inventory slot. Any item can be stacked, including tools. Range is 1-255. Values above 255 are not displayed in-game.
 * : For armor, the amount of wear they have suffered. The maximum durability of the armor means undamaged. When the Damage reaches 0, it breaks and disappears.
 * : The dimension the player is in. 0 is the Overworld.
 * : Each TAG_Compound in this list defines an item the player is carrying or holding.
 * Inventory item data
 * : Indicates which inventory slot this item is in.
 * : Item or Block ID.
 * : Number of items stacked in this inventory slot. Any item can be stacked, including tools. Range is 1-255. Values above 255 are not displayed in-game.
 * : For tools, the amount of wear they have suffered. The maximum durability of the tool (for example, 33 for golden tools) means undamaged. When the Damage reaches 0, it breaks and disappears.
 * : The score of the player.
 * : 1 or 0 (true/false) - true if the player was in a bed when this tag was saved; has no effect on whether the player is in a bed when they log in.
 * : The number of ticks the player had been in bed when this tag was saved. No effect.
 * : X coordinate of the player's spawn position. Default is 0.
 * : Y coordinate of the player's spawn position. Default is 64.
 * : Z coordinate of the player's spawn position. Default is 0.
 * : The abilities this player has.
 * : 1 or 0 (true/false) - true if the player can fly.
 * : 1 or 0 (true/false) - true if the player is currently flying.
 * : 1 or 0 (true/false) - true if the player is immune to all damage and harmful effects except for void damage.
 * : 1 or 0 (true/false) - true if the player can place and destroy blocks.
 * : 1 or 0 (true/false) - true if the player can instantly destroy blocks.
 * : Random number providing the Random Seed for the terrain.
 * : Estimated size of the entire world in bytes.
 * : X coordinate of the world's spawn position. Default is 0.
 * : Y coordinate of the world's spawn position. Default is 64.
 * : Z coordinate of the world's spawn position. Default is 0.
 * : Version of Bedrock Edition NBT, is 3.
 * : Stores the current "time of day" in ticks. There are 20 ticks per real-life second, and 14400 ticks per Minecraft day/night cycle, making the full cycle length 12 minutes—8 minutes shorter than the standard 20 minute day/night cycle. 0 is the start of daytime, 7200 is the start of sunset, 8280 is the start of nighttime, 13320 is the start of sunrise, and 14400 is daytime again. The value stored in level.dat is always increasing and can be larger than 14400, but the "time of day" is always modulo 14400 of the "Time" field value.
 * : Added in 8.0. Default is 18446744073709552000.
 * : Disable (0) or enable (1) mob spawning.

chunks.dat
This file stores all the terrain data that makes up a world. It is comprised of chunks which are 16x16x128 (XZY) block sections of the terrain. It can store a maximum of 1024 chunks (32x32) and 512x512x128 (33,554,432) blocks, however, the game only generates 256 chunks (16x16) and 256x256x128 (8,388,608) blocks by default.

The file is separated into 4kb sectors (4,096 bytes). The first sector is the "chunk index" which defines where in the file and world a specific chunk is located. Every 4 bytes of the chunk index represents 1 chunk. Every 128 bytes of the chunk index represents a column of 32 chunks along the Z axis (North to South). Each subsequent 128 byte section represents 1 row of chunks along the X axis (West to East). But in a default world generated by the game, only 16 chunks are defined for each column and row.

The format of each chunk in the chunk index is only 4 bytes. Ex:. The first byte describes how many 4kb sectors make up the chunk's data. In practice, this is always 21 (0x15). The next three bytes is a little-endian number describing how many 4kb sectors from the start of the file exist before the chunk data begins. If a chunk is not present, all 4 bytes will be zero.

As an example, if a chunk in the chunk index at 1,0 (X,Z) reads  we can locate the chunk data within the file. First we get the decimal representation of the last three bytes which are in little-endian  equals   in decimal. Next we calculate the offset by multiplying our result by the size of a sector. Last we get the decimal representation of the first byte which is always 21 (0x15) and multiply it by the size of a sector. As a result, we know this chunk is located at the decimal offset of  and is   bytes in size.

The actual chunk data stores all the terrain data. This includes blocks, data, skylight, blocklight, and biomes.

The first 4 bytes of the chunk will always be. This is believed to be a magic header to confirm that the following data is indeed chunk data.

The next 32,768 bytes contains the block data. The block order is YZX. Every 1 byte is equivalent to going up vertically along the Y axis. After 128 bytes, the height limit of the world is reached, so we move South 1 block along the Z axis and repeat. After 2,048 bytes (128*16) 1 column of the chunk is finished, so we move East 1 block along the X axis and repeat. In most programming languages, this is just a basic 3d array  ([x][z][y]). To reiterate, every 128 blocks is a column on the Z axis, every 16 columns is a row on the X axis.

The next 16,384 bytes contains the "data" data. Otherwise known at damage, meta, or auxiliary data. It's what gives wool its color and chests their direction etc. Just like the block data, the order is YZX. Since data values only range from 0-15, only half a byte is needed to represent 1 block. So, 1 byte actually represents 2 blocks. Hence why the data section is half as big as the block section. This data is big-endian, so a byte like  actually means the first block at this location has a data value of f, and the second block at this location has a data value of 2.

The next 16,384 bytes contains the skylight data. The format is identical to the previous "data" format. If a skylight value is f, that means the sunlight is fully lighting that block (like air or glass). The less sunlight is present in that block, the lower the value (like semi-transparent blocks such as leaves or water). And when the skylight value is 0, no sunlight is present in that block (like stone or dirt). Because the game automatically generates lighting, it is unimportant to modify this part of the file when generating a world via an outside program.

The next 16,384 bytes contains the blocklight data. The format is identical to the previous skylight format. If a blocklight value is f, that means the block is emitting the max amount of light (like glowstone). The less light a block emits, the lower the value (like powered redstone). And when the blocklight value is 0, no light is being emitted from that block. Because the game automatically generates lighting, it is unimportant to modify this part of the file when generating a world via an outside program.

The last 256 bytes contains the biome data. Each byte corresponds to a specific biome type. The order is XZ. Every 16 bytes is a new row.

entities.dat
This file uses the modified little endian uncompressed NBT format. It appears to store entity information using a format based on the Alpha Level Chunk Format. It also stores tile entity information as well.

The file has a 12 byte header. It begins with the ASCII Characters "ENT", then one zero byte, then a little-endian integer with the value 1, followed by another little endian integer stating the length of the file in bytes, not counting the header.

NBT Structure

 * Root compound tag.
 * : Each TAG_Compound in this list defines an entity in the world. See Entity Format below.
 * : Each TAG_Compound in this list defines a Tile entity, such as a furnace, in the world.

Entity Format
Every entity is an unnamed TAG_Compound contained in the Entities list of a chunk file. The sole exception is the Player entity, stored in level.dat.

All entities share this base:


 * Entity data
 * : Entity Type ID. Known values are 13 for Sheep, 32 for Zombie, and 64 for item drops.
 * : 3 TAG_Floats describing the current X,Y,Z position of the entity.
 * : 3 TAG_Floats describing the current dX,dY,dZ velocity of the entity. (Note: 0,0,0 is no motion.)
 * : Two TAG_Floats representing rotation in degrees.
 * : The entity's rotation clockwise around the Y axis (called yaw). Due west is 0. Can have large values because it accumulates all of the entity's lateral rotation throughout the game.
 * : The entity's declination from the horizon (called pitch). Horizontal is 0. Positive values look downward. Does not exceed positive or negative 90 degrees.
 * : Distance the entity has fallen. Larger values cause more damage when the entity lands.
 * : Number of ticks until the fire is put out. Negative values reflect how long the entity can stand in fire before burning.
 * : How much air the entity has, in ticks. Fills to a maximum of 300 in air. Decreases while underwater.
 * : 1 if the entity is touching the ground.

ZombieFace.png Mobs

 * Additional fields for mobs:


 * : Number of ticks the entity's "invincibility shield" is lasting after the entity was last struck.
 * : Number of ticks the entity has been dead for. Controls death animations.
 * : Amount of health the entity has. Players and enemies normally have up to 20 health. Livestock has up to 10 health.
 * : Unknown, maybe time invincible after being hit


 * Additional field for animals such as Sheep:


 * : Age of the animal.

Sheep has two additional fields:


 * : 1 or 0 (true/false) - true if the sheep has been shorn.
 * : 0 to 15 - see wool data values for a mapping to colors. There is evidence that this value does not affect sheep rendering, but does affect wool drops.


 * Cobblestone.png Additional fields for Item:


 * : Starts at 5, and currently only decreases as the item takes fire damage. When health reaches 0, the item is destroyed.
 * : The amount of time an item has been "untouched" on the ground. After 2400 'ticks', or 2 minutes, the item is destroyed.
 * : Item data
 * : Item or Block ID.
 * : The amount of wear each item has suffered. 0 means undamaged. When the Damage exceeds the item's durability, it breaks and disappears. Only tools and armor accumulate damage normally.
 * : Number of items contained in this item drop entity. Any item can be stacked, including tools, armor, and vehicles. Range is 1-255.