我目前正在开发 NBT 阅读器和编写器来编辑 Minecraft 地图(玩家数据和块本身)。我已经完成了 NBTData 的读取,并且能够编写一个 level.dat 文件来编辑一些玩家数据。
不幸的是,我仍然无法将我的 NBT 二进制数据写入区域文件,因为 Minecraft 不接受我的压缩方法。每当我尝试加载我编辑的块时,它都会给我一个错误,即它找不到 ZLib 压缩的结尾或者它是一种无效的压缩方法(我通过终端启动我的世界时发现了这些错误)。
我正在使用 Mac OSX 附带的 ZLib 库,并且编辑器是用 C++ 编写的。
这是我的压缩代码:
compressionData* compress(unsigned char* buf, int size)
{
vector<char> data = vector<char>();
for(int i = 0;i<size;i++)
data.push_back(buf[i]);
int ret;
z_stream zs;
char buff[4096];
std::vector<char> out_data;
// initialize zlib structure
memset(&zs, 0, sizeof(zs));
if(deflateInit(&zs, Z_BEST_COMPRESSION) != Z_OK)
return false;
zs.next_in = (Bytef *) data.data();
zs.avail_in = data.size();
// deflate blocks
do {
zs.next_out = reinterpret_cast<Bytef *>(buff);
zs.avail_out = 4096;
// deflate data and place in out_data
ret = deflate(&zs, Z_FINISH);
out_data.insert(out_data.end(), buff, buff + zs.total_out);
} while(ret == Z_OK);
// check for errors
deflateEnd(&zs);
if (ret != Z_STREAM_END)
return false;
// assign to data
data = out_data;
compressionData *rett = new compressionData();
rett->buf = (unsigned char*)malloc(data.size());
SharedStats::getSharedStats()->mallocated++;
for(int i = 0;i<data.size();i++)
rett->buf[i] = data.at(i);
rett->size = (int)data.size();
return rett;
}
compressionData 对象是一个结构,它只包含一个包含数据的无符号字符数组和一个表示数据长度的 int,以字节为单位。
我应该对 Minecraft 块使用哪种 ZLib 加密方法?原始输入块总是以这三个字节开头:02 78 9C,我的块以 02 78 DA 开头。
来自块的所有数据都写入一个区域文件,Minecraft 确实可以识别它们,只是它不喜欢压缩方法。
伟人,艾伦