Class RegionFile

java.lang.Object
net.glowstone.io.anvil.RegionFile

public class RegionFile extends Object
Interfaces with region files on the disk

Region File Format

Concept: The minimum unit of storage on hard drives is 4KB. 90% of Minecraft chunks are smaller than 4KB. 99% are smaller than 8KB. Write a simple container to store chunks in single files in runs of 4KB sectors.

Each region file represents a 32x32 group of chunks. The conversion from chunk number to region number is floor(coord / 32): a chunk at (30, -3) would be in region (0, -1), and one at (70, -30) would be at (3, -1). Region files are named "r.x.z.data", where x and z are the region coordinates.

A region file begins with a 4KB header that describes where chunks are stored in the file. A 4-byte big-endian integer represents sector offsets and sector counts. The chunk offset for a chunk (x, z) begins at byte 4*(x+z*32) in the file. The bottom byte of the chunk offset indicates the number of sectors the chunk takes up, and the top 3 bytes represent the sector number of the chunk. Given a chunk offset o, the chunk data begins at byte 4096*(o/256) and takes up at most 4096*(o%256) bytes. A chunk cannot exceed 1MB in size. If a chunk offset is 0, the corresponding chunk is not stored in the region file.

Chunk data begins with a 4-byte big-endian integer representing the chunk data length in bytes, not counting the length field. The length must be smaller than 4096 times the number of sectors. The next byte is a version field, to allow backwards-compatible updates to how chunks are encoded.

A version of 1 represents a gzipped NBT file. The gzipped data is the chunk length - 1.

A version of 2 represents a deflated (zlib compressed) NBT file. The deflated data is the chunk length - 1.

  • Constructor Details

    • RegionFile

      public RegionFile(File path) throws IOException
      Opens a region file for reading and writing, creating it if it doesn't exist.
      Parameters:
      path - the file path; must be in an existing folder
      Throws:
      IOException - if the file cannot be opened
  • Method Details

    • getSizeDelta

      public int getSizeDelta()
      Returns how much the region file has grown since this function was last called.
      Returns:
      the growth in bytes
    • getChunkDataInputStream

      public DataInputStream getChunkDataInputStream(int x, int z) throws IOException
      Gets an (uncompressed) stream representing the chunk data. Returns null if the chunk is not found or an error occurs.
      Parameters:
      x - the chunk X coordinate relative to the region
      z - the chunk Z coordinate relative to the region
      Returns:
      an input stream with the chunk data, or null if the chunk is missing
      Throws:
      IOException - if the file cannot be read, or the chunk is invalid
    • getChunkDataOutputStream

      public DataOutputStream getChunkDataOutputStream(int x, int z)
      Creates a DataOutputStream to write a chunk to a byte.
      Parameters:
      x - the chunk X coordinate within the region
      z - the chunk Z coordinate within the region
      Returns:
      a DataOutputStream, backed by memory, that can prepare the chunk for writing to disk.
    • write

      protected void write(int x, int z, byte[] data, int length) throws IOException
      Throws:
      IOException
    • hasChunk

      public boolean hasChunk(int x, int z)
    • close

      public void close() throws IOException
      Throws:
      IOException
    • getLastModified

      public long getLastModified()
      Returns the modification timestamp of the region file when it was first opened by this instance, or zero if this instance created the file. The timestamp is in milliseconds since the Unix epoch (see File.lastModified()).
      Returns:
      the modification timestamp