Nick Sotiros
Nick Sotiros

Reputation: 2310

How to deflate minecraft chunk in c#?

So I am trying to make my own minecraft map editor in Unity3d which uses c#. I am using this as a reference https://minecraft.gamepedia.com/Region_file_format. I am able to parse the region file's chunk table and I can then use the table to find the compressed chunks starting with the zlib magic bytes 78 9C. My idea is to use System.IO.Compression.DeflateStream to decompress this chunk of data but when I do this I get an error IOException: Corrupted data ReadInternal coming from the CheckResult method of DelfateStreamNative. If I export the chunk to a temporary file and use nodejs zlib to inflate it, then it works but I think it is skipping the checksum because no matter how much data I give it, it works and gives me something back.

I can't imagine that the .NET inflator is broken so I must be doing something wrong. The compressed chunk length I parse before the compressed data seems to be wrong because my first chunk is said to be 644 bytes but when I look at the file in a hexdump I have 1,230 bytes before the zero padding. Unfortunately the 3 bit header of the zlib block indicates that the block is dynamically compressed so I cannot easily determine the EOB code and I really don't understand RFC 1951 so figuring out where the deflate buffer ends and the checksum starts is beyond me. And again nodejs zlib doesn't care if I give it 644 bytes or 1,230, but to get the full decompressed chunk I assume I need to give it all the compressed data.

Has anyone who has decompress minecraft chunks embedded in anvil region files give me some insights?

Upvotes: 1

Views: 685

Answers (1)

Nick Sotiros
Nick Sotiros

Reputation: 2310

So I compiled the puff.c example from github which is meant to demonstrate inflating zlib buffers and noticed that the parser was not parsing the first two 'file magic' bytes of the buffer, which I don't understand how it knows the window size since that is encoded in those bytes. But anyways I got the idea that the .NET inflator also doesn't want these bytes. And bam! It parses. So some tips for anyone wanting to inflate minecraft chunks, you need to create your seek offset into the .mca file as sectorIndex * 4096 + 7 not sectorIndex * 4096 + 5 and for anyone getting the checksum error from System.IO.Compression.DeflateStream perhaps you need to make sure you are sending it an RFC 1951 buffer and not an RFC 1950 buffer.

Upvotes: 1

Related Questions