From e30c1b3c03a3357ac31bf0e6fa63282f064f8386 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 6 Sep 2024 12:25:52 +0300 Subject: [PATCH] upgrade regions format version to 3 --- res/texts/en_US.txt | 1 + res/texts/ru_RU.txt | 1 + src/coders/compression.cpp | 7 ++- src/constants.hpp | 2 +- src/content/ContentReport.cpp | 14 +++++- src/files/RegionsLayer.cpp | 82 +++++++++++++++++++--------------- src/files/WorldConverter.cpp | 11 +++-- src/files/WorldFiles.cpp | 11 +++++ src/files/WorldFiles.hpp | 2 + src/files/WorldRegions.cpp | 54 +++++++++++----------- src/files/WorldRegions.hpp | 22 ++++----- src/files/compatibility.cpp | 7 ++- src/logic/EngineController.cpp | 3 +- src/voxels/Chunk.cpp | 60 +------------------------ src/voxels/Chunk.hpp | 10 +---- 15 files changed, 138 insertions(+), 149 deletions(-) diff --git a/res/texts/en_US.txt b/res/texts/en_US.txt index f36f12a7..9cf71339 100644 --- a/res/texts/en_US.txt +++ b/res/texts/en_US.txt @@ -1,6 +1,7 @@ # Menu menu.missing-content=Missing Content! world.convert-request=Content indices have changed! Convert world files? +world.upgrade-request=World format is outdated! Convert world files? pack.remove-confirm=Do you want to erase all pack(s) content from the world forever? error.pack-not-found=Could not to find pack error.dependency-not-found=Dependency pack is not found diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index f8abdd9b..20021b53 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -46,6 +46,7 @@ world.generators.default=Обычный world.generators.flat=Плоский world.Create World=Создать Мир world.convert-request=Есть изменения в индексах! Конвертировать мир? +world.upgrade-request=Формат мира устарел! Конвертировать мир? world.delete-confirm=Удалить мир безвозвратно? # Настройки diff --git a/src/coders/compression.cpp b/src/coders/compression.cpp index 74f68528..9f7b551e 100644 --- a/src/coders/compression.cpp +++ b/src/coders/compression.cpp @@ -82,7 +82,12 @@ std::unique_ptr compression::decompress( } case Method::EXTRLE16: { auto decompressed = std::make_unique(dstlen); - extrle::decode16(src, srclen, decompressed.get()); + size_t decoded = extrle::decode16(src, srclen, decompressed.get()); + if (decoded != dstlen) { + throw std::runtime_error( + "expected decompressed size " + std::to_string(dstlen) + + " got " + std::to_string(decoded)); + } return decompressed; } case Method::GZIP: { diff --git a/src/constants.hpp b/src/constants.hpp index b1ae11d4..da4acfc9 100644 --- a/src/constants.hpp +++ b/src/constants.hpp @@ -17,7 +17,7 @@ inline constexpr bool ENGINE_DEBUG_BUILD = true; inline const std::string ENGINE_VERSION_STRING = "0.23"; /// @brief world regions format version -inline constexpr uint REGION_FORMAT_VERSION = 2; +inline constexpr uint REGION_FORMAT_VERSION = 3; /// @brief max simultaneously open world region files inline constexpr uint MAX_OPEN_REGION_FILES = 32; diff --git a/src/content/ContentReport.cpp b/src/content/ContentReport.cpp index 1e524309..a8fc806d 100644 --- a/src/content/ContentReport.cpp +++ b/src/content/ContentReport.cpp @@ -55,7 +55,9 @@ std::shared_ptr ContentReport::create( report->items.setup(itemlist.get(), content->items); report->buildIssues(); - if (report->hasContentReorder() || report->hasMissingContent()) { + if (report->isUpgradeRequired() || + report->hasContentReorder() || + report->hasMissingContent()) { return report; } else { return nullptr; @@ -79,6 +81,16 @@ static void build_issues( void ContentReport::buildIssues() { build_issues(issues, blocks); build_issues(issues, items); + + if (regionsVersion < REGION_FORMAT_VERSION) { + for (int layer = REGION_LAYER_VOXELS; + layer < REGION_LAYERS_COUNT; + layer++) { + ContentIssue issue {ContentIssueType::REGION_FORMAT_UPDATE}; + issue.regionLayer = static_cast(layer); + issues.push_back(issue); + } + } } const std::vector& ContentReport::getIssues() const { diff --git a/src/files/RegionsLayer.cpp b/src/files/RegionsLayer.cpp index 3f0101f4..027d6bf3 100644 --- a/src/files/RegionsLayer.cpp +++ b/src/files/RegionsLayer.cpp @@ -13,14 +13,14 @@ static fs::path get_region_filename(int x, int z) { /// @brief Read missing chunks data (null pointers) from region file static void fetch_chunks(WorldRegion* region, int x, int z, regfile* file) { auto* chunks = region->getChunks(); - uint32_t* sizes = region->getSizes(); + auto sizes = region->getSizes(); for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { int chunk_x = (i % REGION_SIZE) + x * REGION_SIZE; int chunk_z = (i / REGION_SIZE) + z * REGION_SIZE; if (chunks[i] == nullptr) { - chunks[i] = - RegionsLayer::readChunkData(chunk_x, chunk_z, sizes[i], file); + chunks[i] = RegionsLayer::readChunkData( + chunk_x, chunk_z, sizes[i][0], sizes[i][1], file); } } } @@ -44,23 +44,26 @@ regfile::regfile(fs::path filename) : file(std::move(filename)) { } } -std::unique_ptr regfile::read(int index, uint32_t& length) { +std::unique_ptr regfile::read(int index, uint32_t& size, uint32_t& srcSize) { size_t file_size = file.length(); size_t table_offset = file_size - REGION_CHUNKS_COUNT * 4; - uint32_t offset; + uint32_t buff32; file.seekg(table_offset + index * 4); - file.read(reinterpret_cast(&offset), 4); - offset = dataio::read_int32_big(reinterpret_cast(&offset), 0); + file.read(reinterpret_cast(&buff32), 4); + uint32_t offset = dataio::le2h(buff32); if (offset == 0) { return nullptr; } file.seekg(offset); - file.read(reinterpret_cast(&offset), 4); - length = dataio::read_int32_big(reinterpret_cast(&offset), 0); - auto data = std::make_unique(length); - file.read(reinterpret_cast(data.get()), length); + file.read(reinterpret_cast(&buff32), 4); + size = dataio::le2h(buff32); + file.read(reinterpret_cast(&buff32), 4); + srcSize = dataio::le2h(buff32); + + auto data = std::make_unique(size); + file.read(reinterpret_cast(data.get()), size); return data; } @@ -150,7 +153,7 @@ WorldRegion* RegionsLayer::getOrCreateRegion(int x, int z) { return region; } -ubyte* RegionsLayer::getData(int x, int z, uint32_t& size) { +ubyte* RegionsLayer::getData(int x, int z, uint32_t& size, uint32_t& srcSize) { int regionX, regionZ, localX, localZ; calc_reg_coords(x, z, regionX, regionZ, localX, localZ); @@ -159,15 +162,17 @@ ubyte* RegionsLayer::getData(int x, int z, uint32_t& size) { if (data == nullptr) { auto regfile = getRegFile({regionX, regionZ}); if (regfile != nullptr) { - auto dataptr = readChunkData(x, z, size, regfile.get()); + auto dataptr = readChunkData(x, z, size, srcSize, regfile.get()); if (dataptr) { data = dataptr.get(); - region->put(localX, localZ, std::move(dataptr), size); + region->put(localX, localZ, std::move(dataptr), size, srcSize); } } } if (data != nullptr) { - size = region->getChunkDataSize(localX, localZ); + auto sizevec = region->getChunkDataSize(localX, localZ); + size = sizevec[0]; + srcSize = sizevec[1]; return data; } return nullptr; @@ -187,47 +192,50 @@ void RegionsLayer::writeRegion(int x, int z, WorldRegion* entry) { char header[REGION_HEADER_SIZE] = REGION_FORMAT_MAGIC; header[8] = REGION_FORMAT_VERSION; - header[9] = 0; // flags + header[9] = static_cast(compression); // FIXME std::ofstream file(filename, std::ios::out | std::ios::binary); file.write(header, REGION_HEADER_SIZE); size_t offset = REGION_HEADER_SIZE; - char intbuf[4] {}; + uint32_t intbuf; uint offsets[REGION_CHUNKS_COUNT] {}; - auto* region = entry->getChunks(); - uint32_t* sizes = entry->getSizes(); + auto region = entry->getChunks(); + auto sizes = entry->getSizes(); for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { ubyte* chunk = region[i].get(); if (chunk == nullptr) { - offsets[i] = 0; - } else { - offsets[i] = offset; - - size_t compressedSize = sizes[i]; - dataio::write_int32_big( - compressedSize, reinterpret_cast(intbuf), 0 - ); - offset += 4 + compressedSize; - - file.write(intbuf, 4); - file.write(reinterpret_cast(chunk), compressedSize); + continue; } + offsets[i] = offset; + + auto sizevec = sizes[i]; + uint32_t compressedSize = sizevec[0]; + uint32_t srcSize = sizevec[1]; + + intbuf = dataio::h2le(compressedSize); + file.write(reinterpret_cast(&intbuf), 4); + offset += 4; + + intbuf = dataio::h2le(srcSize); + file.write(reinterpret_cast(&intbuf), 4); + offset += 4; + + file.write(reinterpret_cast(chunk), compressedSize); + offset += compressedSize; } for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { - dataio::write_int32_big( - offsets[i], reinterpret_cast(intbuf), 0 - ); - file.write(intbuf, 4); + intbuf = dataio::h2le(offsets[i]); + file.write(reinterpret_cast(&intbuf), 4); } } std::unique_ptr RegionsLayer::readChunkData( - int x, int z, uint32_t& length, regfile* rfile + int x, int z, uint32_t& size, uint32_t& srcSize, regfile* rfile ) { int regionX, regionZ, localX, localZ; calc_reg_coords(x, z, regionX, regionZ, localX, localZ); int chunkIndex = localZ * REGION_SIZE + localX; - return rfile->read(chunkIndex, length); + return rfile->read(chunkIndex, size, srcSize); } diff --git a/src/files/WorldConverter.cpp b/src/files/WorldConverter.cpp index 5d24889d..396f1f16 100644 --- a/src/files/WorldConverter.cpp +++ b/src/files/WorldConverter.cpp @@ -167,7 +167,7 @@ void WorldConverter::upgradeRegion( void WorldConverter::convertVoxels(const fs::path& file, int x, int z) const { logger.info() << "converting voxels region " << x << "_" << z; - wfile->getRegions().processRegion(x, z, REGION_LAYER_VOXELS, CHUNK_DATA_LEN, + wfile->getRegions().processRegion(x, z, REGION_LAYER_VOXELS, [=](std::unique_ptr data, uint32_t*) { Chunk::convert(data.get(), report.get()); return data; @@ -238,8 +238,13 @@ bool WorldConverter::isActive() const { } void WorldConverter::write() { - logger.info() << "writing world"; - wfile->write(nullptr, upgradeMode ? nullptr : content); + if (upgradeMode) { + logger.info() << "refreshing version"; + wfile->patchIndicesVersion("region-version", REGION_FORMAT_VERSION); + } else { + logger.info() << "writing world"; + wfile->write(nullptr, content); + } } void WorldConverter::waitForEnd() { diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 54e96759..8fb1913d 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -172,6 +172,17 @@ bool WorldFiles::readResourcesData(const Content* content) { return true; } +void WorldFiles::patchIndicesVersion(const std::string& field, uint version) { + fs::path file = getIndicesFile(); + if (!fs::is_regular_file(file)) { + logger.error() << file.filename().u8string() << " does not exists"; + return; + } + auto root = files::read_json(file); + root->put(field, version); + files::write_json(file, root.get(), true); +} + static void erase_pack_indices(dynamic::Map* root, const std::string& id) { auto prefix = id + ":"; auto blocks = root->list("blocks"); diff --git a/src/files/WorldFiles.hpp b/src/files/WorldFiles.hpp index cb9c4b45..32b64060 100644 --- a/src/files/WorldFiles.hpp +++ b/src/files/WorldFiles.hpp @@ -51,6 +51,8 @@ public: std::optional readWorldInfo(); bool readResourcesData(const Content* content); + void patchIndicesVersion(const std::string& field, uint version); + /// @brief Write all unsaved data to world files /// @param world target world /// @param content world content diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index 500c21a0..d0fb57d3 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -14,7 +14,7 @@ WorldRegion::WorldRegion() : chunksData( std::make_unique[]>(REGION_CHUNKS_COUNT) ), - sizes(std::make_unique(REGION_CHUNKS_COUNT)) { + sizes(std::make_unique(REGION_CHUNKS_COUNT)) { } WorldRegion::~WorldRegion() = default; @@ -30,23 +30,23 @@ std::unique_ptr* WorldRegion::getChunks() const { return chunksData.get(); } -uint32_t* WorldRegion::getSizes() const { +glm::u32vec2* WorldRegion::getSizes() const { return sizes.get(); } void WorldRegion::put( - uint x, uint z, std::unique_ptr data, uint32_t size + uint x, uint z, std::unique_ptr data, uint32_t size, uint32_t srcSize ) { size_t chunk_index = z * REGION_SIZE + x; chunksData[chunk_index] = std::move(data); - sizes[chunk_index] = size; + sizes[chunk_index] = glm::u32vec2(size, srcSize); } ubyte* WorldRegion::getChunkData(uint x, uint z) { return chunksData[z * REGION_SIZE + x].get(); } -uint WorldRegion::getChunkDataSize(uint x, uint z) { +glm::u32vec2 WorldRegion::getChunkDataSize(uint x, uint z) { return sizes[z * REGION_SIZE + x]; } @@ -56,7 +56,7 @@ WorldRegions::WorldRegions(const fs::path& directory) : directory(directory) { } auto& voxels = layers[REGION_LAYER_VOXELS]; voxels.folder = directory / fs::path("regions"); - voxels.compression = compression::Method::EXTRLE8; + voxels.compression = compression::Method::EXTRLE16; auto& lights = layers[REGION_LAYER_LIGHTS]; lights.folder = directory / fs::path("lights"); @@ -85,8 +85,9 @@ void WorldRegions::put( int z, RegionLayerIndex layerid, std::unique_ptr data, - size_t size + size_t srcSize ) { + size_t size = srcSize; auto& layer = layers[layerid]; if (layer.compression != compression::Method::NONE) { data = compression::compress( @@ -97,7 +98,7 @@ void WorldRegions::put( WorldRegion* region = layer.getOrCreateRegion(regionX, regionZ); region->setUnsaved(true); - region->put(localX, localZ, std::move(data), size); + region->put(localX, localZ, std::move(data), size, srcSize); } static std::unique_ptr write_inventories( @@ -188,30 +189,35 @@ void WorldRegions::put(Chunk* chunk, std::vector entitiesData) { std::unique_ptr WorldRegions::getVoxels(int x, int z) { uint32_t size; + uint32_t srcSize; auto& layer = layers[REGION_LAYER_VOXELS]; - auto* data = layer.getData(x, z, size); + auto* data = layer.getData(x, z, size, srcSize); if (data == nullptr) { return nullptr; } - return compression::decompress(data, size, CHUNK_DATA_LEN, layer.compression); + assert(srcSize == CHUNK_DATA_LEN); + return compression::decompress(data, size, srcSize, layer.compression); } std::unique_ptr WorldRegions::getLights(int x, int z) { uint32_t size; + uint32_t srcSize; auto& layer = layers[REGION_LAYER_LIGHTS]; - auto* bytes = layer.getData(x, z, size); + auto* bytes = layer.getData(x, z, size, srcSize); if (bytes == nullptr) { return nullptr; } auto data = compression::decompress( - bytes, size, LIGHTMAP_DATA_LEN, layer.compression + bytes, size, srcSize, layer.compression ); + assert(srcSize == LIGHTMAP_DATA_LEN); return Lightmap::decode(data.get()); } chunk_inventories_map WorldRegions::fetchInventories(int x, int z) { uint32_t bytesSize; - auto bytes = layers[REGION_LAYER_INVENTORIES].getData(x, z, bytesSize); + uint32_t srcSize; + auto bytes = layers[REGION_LAYER_INVENTORIES].getData(x, z, bytesSize, srcSize); if (bytes == nullptr) { return {}; } @@ -221,7 +227,7 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) { void WorldRegions::processInventories( int x, int z, const inventoryproc& func ) { - processRegion(x, z, REGION_LAYER_INVENTORIES, 0, + processRegion(x, z, REGION_LAYER_INVENTORIES, [=](std::unique_ptr data, uint32_t* size) { auto inventories = load_inventories(data.get(), *size); for (const auto& [_, inventory] : inventories) { @@ -236,7 +242,8 @@ dynamic::Map_sptr WorldRegions::fetchEntities(int x, int z) { return nullptr; } uint32_t bytesSize; - const ubyte* data = layers[REGION_LAYER_ENTITIES].getData(x, z, bytesSize); + uint32_t srcSize; + const ubyte* data = layers[REGION_LAYER_ENTITIES].getData(x, z, bytesSize, srcSize); if (data == nullptr) { return nullptr; } @@ -248,7 +255,7 @@ dynamic::Map_sptr WorldRegions::fetchEntities(int x, int z) { } void WorldRegions::processRegion( - int x, int z, RegionLayerIndex layerid, uint32_t dataLen, const regionproc& func + int x, int z, RegionLayerIndex layerid, const regionproc& func ) { auto& layer = layers[layerid]; if (layer.getRegion(x, z)) { @@ -263,24 +270,21 @@ void WorldRegions::processRegion( int gx = cx + x * REGION_SIZE; int gz = cz + z * REGION_SIZE; uint32_t length; + uint32_t srcSize; auto data = - RegionsLayer::readChunkData(gx, gz, length, regfile.get()); + RegionsLayer::readChunkData(gx, gz, length, srcSize, regfile.get()); if (data == nullptr) { continue; } - uint32_t totalLength = dataLen; if (layer.compression != compression::Method::NONE) { - if (dataLen == 0) { - throw std::invalid_argument("invalid data length"); - } data = compression::decompress( - data.get(), length, dataLen, layer.compression + data.get(), length, srcSize, layer.compression ); } else { - totalLength = length; + srcSize = length; } - if (auto writeData = func(std::move(data), &totalLength)) { - put(gx, gz, layerid, std::move(writeData), totalLength); + if (auto writeData = func(std::move(data), &srcSize)) { + put(gx, gz, layerid, std::move(writeData), srcSize); } } } diff --git a/src/files/WorldRegions.hpp b/src/files/WorldRegions.hpp index fecd30fa..511107bf 100644 --- a/src/files/WorldRegions.hpp +++ b/src/files/WorldRegions.hpp @@ -38,21 +38,21 @@ public: class WorldRegion { std::unique_ptr[]> chunksData; - std::unique_ptr sizes; + std::unique_ptr sizes; bool unsaved = false; public: WorldRegion(); ~WorldRegion(); - void put(uint x, uint z, std::unique_ptr data, uint32_t size); + void put(uint x, uint z, std::unique_ptr data, uint32_t size, uint32_t srcSize); ubyte* getChunkData(uint x, uint z); - uint getChunkDataSize(uint x, uint z); + glm::u32vec2 getChunkDataSize(uint x, uint z); void setUnsaved(bool unsaved); bool isUnsaved() const; std::unique_ptr* getChunks() const; - uint32_t* getSizes() const; + glm::u32vec2* getSizes() const; }; struct regfile { @@ -63,7 +63,7 @@ struct regfile { regfile(fs::path filename); regfile(const regfile&) = delete; - std::unique_ptr read(int index, uint32_t& length); + std::unique_ptr read(int index, uint32_t& size, uint32_t& srcSize); }; using regionsmap = std::unordered_map>; @@ -152,9 +152,10 @@ struct RegionsLayer { /// @brief Get chunk data. Read from file if not loaded yet. /// @param x chunk x coord /// @param z chunk z coord - /// @param size [out] chunk data length + /// @param size [out] compressed chunk data length + /// @param size [out] source chunk data length /// @return nullptr if no saved chunk data found - [[nodiscard]] ubyte* getData(int x, int z, uint32_t& size); + [[nodiscard]] ubyte* getData(int x, int z, uint32_t& size, uint32_t& srcSize); /// @brief Write or rewrite region file /// @param x region X @@ -167,11 +168,12 @@ struct RegionsLayer { /// @brief Read chunk data from region file /// @param x chunk x coord /// @param z chunk z coord - /// @param length [out] chunk data length + /// @param size [out] compressed chunk data length + /// @param srcSize [out] source chunk data length /// @param rfile region file /// @return nullptr if chunk is not present in region file [[nodiscard]] static std::unique_ptr readChunkData( - int x, int z, uint32_t& length, regfile* rfile + int x, int z, uint32_t& size, uint32_t& srcSize, regfile* rfile ); }; @@ -229,7 +231,7 @@ public: /// @param layerid regions layer index /// @param func processing callback void processRegion( - int x, int z, RegionLayerIndex layerid, uint32_t dataLen, const regionproc& func); + int x, int z, RegionLayerIndex layerid, const regionproc& func); void processInventories( int x, int z, const inventoryproc& func); diff --git a/src/files/compatibility.cpp b/src/files/compatibility.cpp index 161527b1..8cdd437d 100644 --- a/src/files/compatibility.cpp +++ b/src/files/compatibility.cpp @@ -12,6 +12,7 @@ static inline size_t VOXELS_DATA_SIZE_V1 = CHUNK_VOL * 4; static inline size_t VOXELS_DATA_SIZE_V2 = CHUNK_VOL * 4; +#include static util::Buffer convert_voxels_1to2(const ubyte* buffer, uint32_t size) { auto data = compression::decompress( buffer, size, VOXELS_DATA_SIZE_V1, compression::Method::EXTRLE8); @@ -30,18 +31,20 @@ static util::Buffer convert_voxels_1to2(const ubyte* buffer, uint32_t siz (static_cast(bid1) << 8) | static_cast(bid2); dst[CHUNK_VOL + i] = ( (static_cast(bst1) << 8) | - static_cast(bst2) + static_cast(bst2) ); } size_t outLen; auto compressed = compression::compress( - data.get(), VOXELS_DATA_SIZE_V2, outLen, compression::Method::EXTRLE16); + dstBuffer.data(), VOXELS_DATA_SIZE_V2, outLen, compression::Method::EXTRLE16); return util::Buffer(std::move(compressed), outLen); } +#include "util/timeutil.hpp" util::Buffer compatibility::convert_region_2to3( const util::Buffer& src, RegionLayerIndex layer ) { + timeutil::ScopeLogTimer log(555); const size_t REGION_CHUNKS = 1024; const size_t HEADER_SIZE = 10; const size_t OFFSET_TABLE_SIZE = REGION_CHUNKS * sizeof(uint32_t); diff --git a/src/logic/EngineController.cpp b/src/logic/EngineController.cpp index 8cb53f28..bbdb06eb 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -73,7 +73,8 @@ void show_convert_request( ) { guiutil::confirm( engine->getGUI(), - langs::get(L"world.convert-request"), + langs::get(report->isUpgradeRequired() ? + L"world.upgrade-request" : L"world.convert-request"), [=]() { auto converter = create_converter(engine, worldFiles, content, report, postRunnable); diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index 80bfcd73..238e2975 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -77,33 +77,6 @@ std::unique_ptr Chunk::clone() const { return other; } -/** - Current chunk format: - - byte-order: big-endian - - [don't panic!] first and second bytes are separated for RLE efficiency - - ```cpp - uint8_t voxel_id_first_byte[CHUNK_VOL]; - uint8_t voxel_id_second_byte[CHUNK_VOL]; - uint8_t voxel_states_first_byte[CHUNK_VOL]; - uint8_t voxel_states_second_byte[CHUNK_VOL]; - ``` - - Total size: (CHUNK_VOL * 4) bytes -*/ -std::unique_ptr Chunk::encode() const { - auto buffer = std::make_unique(CHUNK_DATA_LEN); - for (uint i = 0; i < CHUNK_VOL; i++) { - buffer[i] = voxels[i].id >> 8; - buffer[CHUNK_VOL + i] = voxels[i].id & 0xFF; - - blockstate_t state = blockstate2int(voxels[i].state); - buffer[CHUNK_VOL * 2 + i] = state >> 8; - buffer[CHUNK_VOL * 3 + i] = state & 0xFF; - } - return buffer; -} - /** Current chunk format: - byte-order: little-endian @@ -115,7 +88,7 @@ std::unique_ptr Chunk::encode() const { Total size: (CHUNK_VOL * 4) bytes */ -std::unique_ptr Chunk::encodeV2() const { +std::unique_ptr Chunk::encode() const { auto buffer = std::make_unique(CHUNK_DATA_LEN); auto dst = reinterpret_cast(buffer.get()); for (uint i = 0; i < CHUNK_VOL; i++) { @@ -126,26 +99,6 @@ std::unique_ptr Chunk::encodeV2() const { } bool Chunk::decode(const ubyte* data) { - for (uint i = 0; i < CHUNK_VOL; i++) { - voxel& vox = voxels[i]; - - ubyte bid1 = data[i]; - ubyte bid2 = data[CHUNK_VOL + i]; - - ubyte bst1 = data[CHUNK_VOL * 2 + i]; - ubyte bst2 = data[CHUNK_VOL * 3 + i]; - - vox.id = - (static_cast(bid1) << 8) | static_cast(bid2); - vox.state = int2blockstate( - (static_cast(bst1) << 8) | - static_cast(bst2) - ); - } - return true; -} - -bool Chunk::decodeV2(const ubyte* data) { auto src = reinterpret_cast(data); for (uint i = 0; i < CHUNK_VOL; i++) { voxel& vox = voxels[i]; @@ -157,17 +110,6 @@ bool Chunk::decodeV2(const ubyte* data) { } void Chunk::convert(ubyte* data, const ContentReport* report) { - for (uint i = 0; i < CHUNK_VOL; i++) { - blockid_t id = - ((static_cast(data[i]) << 8) | - static_cast(data[CHUNK_VOL + i])); - blockid_t replacement = report->blocks.getId(id); - data[i] = replacement >> 8; - data[CHUNK_VOL + i] = replacement & 0xFF; - } -} - -void Chunk::convertV2(ubyte* data, const ContentReport* report) { auto buffer = reinterpret_cast(data); for (uint i = 0; i < CHUNK_VOL; i++) { blockid_t id = dataio::le2h(buffer[i]); diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 382c69f3..79f75c28 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -66,20 +66,12 @@ public: flags.unsaved = true; } - /// @brief Encode chunk to bytes array of size CHUNK_DATA_LEN - /// @see /doc/specs/outdated/region_voxels_chunk_spec_v1.md - std::unique_ptr encode() const; - /// @brief Encode chunk to bytes array of size CHUNK_DATA_LEN /// @see /doc/specs/region_voxels_chunk_spec.md - std::unique_ptr encodeV2() const; + std::unique_ptr encode() const; /// @return true if all is fine bool decode(const ubyte* data); - /// @return true if all is fine - bool decodeV2(const ubyte* data); - static void convert(ubyte* data, const ContentReport* report); - static void convertV2(ubyte* data, const ContentReport* report); };