私は現在、Minecraft マップ (プレイヤー データとチャンク自体の両方) を編集するための NBT リーダーとライターに取り組んでいます。NBTData の読み取りがすべて完了し、level.dat ファイルを書き込んでプレーヤー データを編集することができました。
残念ながら、Minecraft が圧縮方法を受け入れないため、NBT バイナリ データをリージョン ファイルに書き込むことができません。編集したチャンクを読み込もうとすると、ZLib 圧縮の末尾が見つからない、または圧縮方法が無効であるというエラーが表示されます (ターミナル経由で minecraft を起動すると、これらのエラーが発生しました)。
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 オブジェクトは、データを含む unsigned char 配列と、データの長さをバイト単位で示す int のみを保持する構造体です。
Minecraft チャンクにはどの ZLib 暗号化方式を使用すればよいですか? 元の入力チャンクは常に次の 3 バイトで始まります: 02 78 9C、私のチャンクは 02 78 DA で始まります。
チャンクからのすべてのデータはリージョン ファイルに書き込まれ、Minecraft はそれらを認識しますが、圧縮方法が気に入らないだけです。
グレイト、アラン