#pragma once #include #include #include #include "Block.h" #include "Chunk.h" #include "Codec.h" #include "World.h" namespace vf { constexpr int anvilRegionSpan = 32; // chunk columns per region side (X and Z) constexpr int32_t heightNone = -2147483647 - 1; // Fixed-width index packer: N palette indices of `bitWidth` bits packed into // 64-bit words, LSB-first, padded so no index straddles a word boundary // (the modern Anvil layout). Round trips exactly for any width in 1..64. class BitPacker { public: static int bitWidthForPalette(std::size_t paletteSize); static std::vector pack(const std::vector& values, int bitWidth); static std::vector unpack(const std::vector& words, int bitWidth, std::size_t count); }; // One 16^3 section: the distinct blocks it uses plus bit-packed indices into // that palette. struct AnvilSection { int sectionY = 0; std::vector palette; int bitWidth = 1; std::vector packed; void encodeFrom(const Chunk& chunk); void decodeTo(Chunk& chunk) const; }; // One chunk column inside a region: its stacked sections plus a heightmap of // the highest non-air world-Y per (x,z) column. struct AnvilColumn { int localX = 0; int localZ = 0; std::vector sections; std::vector heightmap; const AnvilSection* section(int sectionY) const; }; // A region v5 blob: a 32x32 tile of chunk columns, each column compressed via // the Codec. Chunks are stored by their world chunk coordinate. class AnvilRegion { public: AnvilRegion() = default; AnvilRegion(int regionX, int regionZ) : regionX(regionX), regionZ(regionZ) {} int rx() const { return regionX; } int rz() const { return regionZ; } void putChunk(const Vec3i& chunkCoord, const Chunk& chunk); bool hasChunk(const Vec3i& chunkCoord) const; bool getChunk(const Vec3i& chunkCoord, Chunk& out) const; std::size_t columnCount() const { return columns.size(); } std::size_t sectionCount() const; int32_t heightAt(int localX, int localZ, int x, int z) const; ByteBuffer serialize() const; static bool deserialize(const uint8_t* data, std::size_t size, AnvilRegion& out); const std::vector& allColumns() const { return columns; } private: AnvilColumn& columnFor(int localX, int localZ); const AnvilColumn* findColumn(int localX, int localZ) const; int regionX = 0; int regionZ = 0; std::vector columns; }; // Splits a world into region v5 tiles by chunk-column position. std::vector anvilRegionsFromWorld(const World& world); // One blob holding every region of a world, and its inverse. ByteBuffer anvilSerializeWorld(const World& world); bool anvilDeserializeWorld(const uint8_t* data, std::size_t size, World& out); } // namespace vf