Untitled

mail@pastecode.io avatar
unknown
java
3 years ago
2.4 kB
1
Indexable
Never
package com.liquake.antidupe.rareitemchecks.utils.chunkfile;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;

import de.tr7zw.changeme.nbtapi.NBTCompound;
import lombok.Getter;

public class RegionFileNBT extends NBTCompound {

    private RandomAccessFile raf;
    @Getter
    private RegionChunkNBT[] chunks;

    public RegionFileNBT(RandomAccessFile raf) throws IOException {
        super(null, null);
        this.raf = raf;
        chunks = new RegionChunkNBT[1024];
        /*
         * 
         * Read the Region file and get all the chunks. Region files can contain a 32x32
         * chunk grid. 32x32 = 1024 chunks
         * 
         * @info Region files begin with an 8kB header containing information about
         * which chunks are present in the region file, when they were last updated, and
         * where they can be found.
         * 
         * @info The location in the region file of a chunk at (x, z) (in chunk
         * coordinates) must be found at byte offset 4 * ((x mod 32) + (z mod 32) * 32)
         * 
         * @info You can found more in:
         * https://minecraft.fandom.com/wiki/Region_file_format#Structure
         * 
         */
        for (int i = 0; i < 1024; i++) {
            // Chunk offset in file
            raf.seek(i * 4);
            byte[] offsetBytes = new byte[3];
            raf.read(offsetBytes);
            int offset = offsetBytes[0] << 16;
            offset |= (offsetBytes[1] & 0xFF) << 8;
            offset |= (offsetBytes[2] & 0xFF);

            // Chunk sector count
            byte sectorCount = raf.readByte();
            if (sectorCount == 0) {
                continue;
            }

            // Timestamps
            raf.seek(4096 + i * 4);
            byte[] timestampBytes = new byte[4];
            raf.read(timestampBytes);
            int timestamp = ByteBuffer.wrap(timestampBytes).getInt();

            raf.seek(4096 * offset);
            byte[] length = new byte[4];
            raf.readFully(length);

            int dataLength = ByteBuffer.wrap(length).getInt();

            raf.seek(4096 * offset + 4); // +4: skip data size
            RegionChunkNBT chunk = new RegionChunkNBT(timestamp, RegionChunkNBT.deserialize(raf, dataLength));
            chunks[i] = chunk;
        }
    }

}