Region file format

The Region file format is a storage format for Minecraft chunks introduced in Minecraft Beta 1.3, in which groups of 32×32 chunks are stored in a region file rather than individually. It could be said that a region is a part of a file system where the header is positions for each file and sector is the allocation size. The system is based on McRegion, a mod by Scaevolus, also known for his development of the Optimine project. The McRegion format was adopted nearly unchanged, except for the addition of a table of chunk update timestamps. JahKob claims that this format is up to 7 times faster than the previous system.

As of Minecraft 1.2, the Region file format has been superseded by the Anvil file format; however, the Anvil file format only made changes to the Chunk format and only changed the region file extensions from ".mcr" to ".mca".

Region File Location
Region files are located in a subfolder of the world directory called "region", and have names in the form r.x.z.mcr, where x and z are the region's coordinates. The coordinates for the region a chunk belongs to can be found by taking the floor of the chunk coordinates divided by 32.

In Java:

int localX = (int)floor(chunkX / 32.0); int localZ = (int)floor(chunkZ / 32.0);

Or in bit-operation(bit shift):

int localX = chunkX >> 5 int localZ = chunkZ >> 5

For example, a chunk at (30, -3) would be in region (0, -1), and one at (70, -30) would be at (2, -1).

Structure
Region files begin with an 8kiB header containing information about which chunks are present in the region file, when they were last updated, and where they can be found. The location in the region file of a chunk at (x, z) (in chunk coordinates) can be found at byte offset 4 * ((x mod 32) + (z mod 32) * 32) in its region file. In case the values of x or z are negative, subtract their value from 32 after calculating the modulo. Its timestamp can be found 4096 bytes later in the file. The remainder of the file consists of data for up to 1024 chunks, interspersed with an arbitrary amount of unused space.

Chunk Location
Location information for a chunk consists of four bytes split into two fields: the first three bytes are a (big-endian) offset in 4KiB sectors from the start of the file, and a remaining byte which gives the length of the chunk (also in 4KiB sectors, rounded up). Chunks will always be less than 1MiB in size. If a chunk isn't present in the region file (e.g. because it hasn't been generated or migrated yet), both fields will be zero.

A chunk with an offset of 2 will begin right after the timestamps table.

Chunk Timestamps
The entries in the timestamp table are individual four-byte big-endian integers, representing the last modification time of a chunk.

Chunk Data
Chunk data begins with a (big-endian) four-byte length field which indicates the exact length of the remaining chunk data in bytes. The following byte indicates the compression scheme used for chunk data, and the remaining (length-1) bytes are the compressed chunk data.

There are currently two defined compression schemes:

If you prefer to read Zlib-compressed chunk data with Deflate (RFC1951), just skip the first two bytes and leave off the last 4 bytes before decompressing.

The uncompressed data is in NBT format and follows the information detailed on the Chunk format article; if compressed with compression scheme 1, the compressed data would be the same as the on-disk content of an Alpha chunk file. Note that chunks will always be saved using compression scheme 2 by the official client.

Migration and level.dat
Beta 1.3 will convert any "old" chunks into region files before loading the world, rather than incrementally as they are loaded during play. As part of the conversion, level.dat will be updated with TAG_Int("version") (note case) set to 19132. Beta 1.3 also introduces a new level name field, TAG_String("LevelName"). There's also introduced new TAG_Byte("Sleeping") in player TAG_Compounds - level.dat in single player, [player name].dat in multiplayer which indicates whether is player in the bed. It has value 1(true) or 0(false). For the beta 1.8, TAG_Int("GameType") was added. In beta 1.9, TAG_byte("hardcore") was added.

The format of level.dat is otherwise unchanged.