Chunks.dat文件格式

来自Survivalcraft 中文百科
跳转至: 导航搜索

Chunks.dat 格式

本文将介绍 1.4 及后续版本的 Chunks.dat 格式。

Chunks.dat 文件以二进制形式存储地形数据。它只储存地形数据。

地形以每 16x16x128 块(Blocks)一组的方式存储于该文件中,在文件标头有一个固定大小的字典(Directory)记录了现有区块(Chunk)的绝对坐标和相对于文件头的偏移量。

并非所有区块都会进行记录,只有被修改过(如放置、打掉方块)的区块才会被保存在该文件。其余区块使用默认的算法生成。

Chunks.dat 包括两个部分:

* 包含所有区块(Chunk)信息的字典(Directory)
* 以数组方式存储的区块(Chunk)数据

字典中的每个记录保存了一个区块的信息。每个记录有 24 字节,共有 65536 个记录保存在字典中(这就表示了单个世界的全部空间)。 未使用的区块用 0 来填充。在65536个记录之后,有一个哨兵记录,它的值总是 0 。整个字典共有 1572888 个字节。

每个区块都有一个标头,它包含了一个用于存储块(Block)的三维数组(16*16*128,x/z/y)和一个用于存储表面点(SurfacePoint)的二维数组(16*16,x/z)。标头的大小为 32 字节。每个块的大小是 4 字节。每个表面点的大小是 8 字节。一个区块总是完整地被存储,就算只有一个方块和算法生成的地形不同。每个区块的大小都是 133152 字节。

数据结构定义(C/C++)

// All data little-endian.

// A single entry in directory of chunks

struct DirectoryEntry
{
    int ChunkX;   // Chunk position, (1 unit equals 16 blocks, must be positive)
    int ChunkZ;   // Chunk position, (1 unit equals 16 blocks, must be positive)
    int Offset;   // Offset of chunk data from the start of file, in bytes
};

// The whole directory of chunks

struct Directory
{
    DirectoryEntry Entries[65536];  // Directory entries, unused entries filled with 0
    DirectoryEntry Guard;           // Guard entry always filled with 0
};

// A single block

struct Block
{
    byte BlockType;  // Type of block (0-air, 1-bedrock, 2-dirt, 3-granite etc.)
    byte BlockData;  // 4 low bits contain light level, 4 high bits contain block-specific data
};

// A single surface point 

struct SurfacePoint
{
    byte MaxHeight;      // Maximum height at this point (non-air blocks)
    byte TempHumidity;   // 4 low bits contain temperature, 4 high bits contain humidity
    byte Unused1;        // Currently unused (must be zero)
    byte Unused2;        // Currently unused (must be zero)
}; 

// Chunk header

struct ChunkHeader
{
    int Magic1;     // Must be 0xDEADBEEF
    int Magic2;     // Must be 0xFFFFFFFF
    int ChunkX;     // Chunk position (1 unit equals 16 blocks, must be positive)
    int ChunkZ;     // Chunk position (1 unit equals 16 blocks, must be positive)
};

// A single chunk

struct Chunk
{
    ChunkHeader Header;           // Chunk header
    Block Blocks[32768];          // Data of all blocks in chunk (16*16*128), in x/z/y order
    SurfacePoint Surface[256];    // Data of all surface points in chunk (16*16), in x/z order
};

// The whole chunks.dat file

struct ChunksFile
{
    Directory Dir;      // Chunks directory
    Chunk Chunks[];     // Array of chunks, variable size (0 to 65536 max)
};

表面点(SurfacePoint)

表面点包含最高高度、温度和湿度数值。理论上这些数值是多余的,因为它能通过游戏引擎重新生成。但是这种重新生成的过程消耗时间很多,因此数据连同区段一同被储存。每个表面点描述了贯穿世界底部和顶部的一条轴(1*1*128)。

温度数值从 0(极寒,-16)15(极热,16)。湿度数值从 0(极干,-16)15(极湿,16)。这两个值能使某些方块颜色发声变化,比如树叶、水、草地。这些方块(如树木)也根据最初生成的地形条件(温度及湿度等)来生成。

最高高度是表面高度内部的指定轴,方块从最低数值(0)到最高数值(128)。所有方块超过的高度都假定仅包含 Non-light 填充方块(主要是空气)。高度值用于加快光学计算。

使用以下公式计算一个表面点的表面排列:

int surfacePointIndex = X + Z * 16;

方块(Block)

BlockType 决定此位置是什么方块,数值从 0~1023。XML 方块数据文件包含了游戏中所有可用方块的详细描述。

BlockData 是与每个方块实例相关联的 8 位数据值。低 4 位包含光值(0=完全黑暗,15=最亮)。高 18 位包含方块的个性值,例如门的开关状态、水位、火把位置等。这些值目前未被归档(This data is undocumented at the moment)。对于大多数方块安全的设为 0。

使用以下公式计算一个方块的索引:

int blockIndex = Y + X * 128 + Z * 128 * 16;

留言