From c5fa6935a6bea4b4d823d860fafadf31c45e0f9b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 12 Jan 2025 01:47:07 +0300 Subject: [PATCH] add metadata to chunk data used in world.get/set_chunk_data --- src/logic/scripting/lua/libs/libworld.cpp | 100 +++++++++------------- 1 file changed, 41 insertions(+), 59 deletions(-) diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 60183ab3..ddba261e 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -7,6 +7,7 @@ #include "coders/compression.hpp" #include "coders/gzip.hpp" #include "coders/json.hpp" +#include "coders/byte_utils.hpp" #include "coders/rle.hpp" #include "engine/Engine.hpp" #include "files/engine_paths.hpp" @@ -123,39 +124,29 @@ static int l_get_generator(lua::State* L) { return lua::pushstring(L, require_world_info().generator); } -static std::vector prepare_chunk_data(const Chunk& chunk, bool compress) { +static std::vector prepare_chunk_data(const Chunk& chunk) { auto data = chunk.encode(); - std::vector chunkData; - if (compress) { - // world.get_chunk_data is only available in the main Lua state - static util::Buffer rleBuffer; - if (rleBuffer.size() < CHUNK_DATA_LEN * 2) { - rleBuffer = util::Buffer(CHUNK_DATA_LEN * 2); - } - size_t rleCompressedSize = - extrle::encode16(data.get(), CHUNK_DATA_LEN, rleBuffer.data()); - - const auto gzipCompressedData = gzip::compress( - rleBuffer.data(), rleCompressedSize - ); - auto tmp = dataio::h2le(rleCompressedSize); - chunkData.reserve(gzipCompressedData.size() + sizeof(tmp)); - chunkData.insert( - chunkData.begin() + 0, (char*)&tmp, ((char*)&tmp) + sizeof(tmp) - ); - chunkData.insert( - chunkData.begin() + sizeof(tmp), - gzipCompressedData.data(), - gzipCompressedData.data() + gzipCompressedData.size() - ); - } else { - chunkData.reserve(CHUNK_DATA_LEN); - chunkData.insert( - chunkData.begin(), data.get(), data.get() + CHUNK_DATA_LEN - ); + /// world.get_chunk_data is only available in the main Lua state + static util::Buffer rleBuffer; + if (rleBuffer.size() < CHUNK_DATA_LEN * 2) { + rleBuffer = util::Buffer(CHUNK_DATA_LEN * 2); } - return chunkData; + size_t rleCompressedSize = + extrle::encode16(data.get(), CHUNK_DATA_LEN, rleBuffer.data()); + + const auto gzipCompressedData = gzip::compress( + rleBuffer.data(), rleCompressedSize + ); + auto metadataBytes = chunk.blocksMetadata.serialize(); + + ByteBuilder builder(2 + 8 + gzipCompressedData.size() + metadataBytes.size()); + builder.putInt16(0); // header + builder.putInt32(gzipCompressedData.size()); + builder.put(gzipCompressedData.data(), gzipCompressedData.size()); + builder.putInt32(metadataBytes.size()); + builder.put(metadataBytes.data(), metadataBytes.size()); + return builder.build(); } static int l_get_chunk_data(lua::State* L) { @@ -166,11 +157,7 @@ static int l_get_chunk_data(lua::State* L) { lua::pushnil(L); return 0; } - bool compress = true; - if (lua::gettop(L) >= 3) { - compress = lua::toboolean(L, 3); - } - auto chunkData = prepare_chunk_data(*chunk, compress); + auto chunkData = prepare_chunk_data(*chunk); return lua::newuserdata(L, std::move(chunkData)); } @@ -178,33 +165,29 @@ static int l_set_chunk_data(lua::State* L) { int x = static_cast(lua::tointeger(L, 1)); int y = static_cast(lua::tointeger(L, 2)); auto buffer = lua::touserdata(L, 3); - bool isCompressed = true; - if (lua::gettop(L) >= 4) { - isCompressed = lua::toboolean(L, 4); - } auto chunk = level->chunks->getChunk(x, y); if (chunk == nullptr) { return 0; } - if (isCompressed) { - std::vector& rawData = buffer->data(); - size_t gzipDecompressedSize = dataio::le2h(*(size_t*)(rawData.data())); - auto rleData = compression::decompress( - rawData.data() + sizeof(gzipDecompressedSize), - buffer->data().size() - sizeof(gzipDecompressedSize), - gzipDecompressedSize, - compression::Method::GZIP - ); - auto data = compression::decompress( - rleData.get(), - gzipDecompressedSize, - CHUNK_DATA_LEN, - compression::Method::EXTRLE16 - ); - chunk->decode(data.get()); - } else { - chunk->decode(buffer->data().data()); - } + + std::vector& rawData = buffer->data(); + + ByteReader reader(rawData.data(), rawData.size()); + + uint16_t header = reader.getInt16(); + size_t gzipCompressedSize = reader.getInt32(); + + auto rleData = gzip::decompress(reader.pointer(), gzipCompressedSize); + reader.skip(gzipCompressedSize); + + /// world.get_chunk_data is only available in the main Lua state + static util::Buffer voxelData (CHUNK_DATA_LEN); + extrle::decode16(rleData.data(), rleData.size(), voxelData.data()); + chunk->decode(voxelData.data()); + + size_t metadataSize = reader.getInt32(); + chunk->blocksMetadata.deserialize(reader.pointer(), metadataSize); + reader.skip(metadataSize); chunk->setModifiedAndUnsaved(); chunk->updateHeights(); @@ -233,7 +216,6 @@ static int l_set_chunk_data(lua::State* L) { } } } - return lua::pushboolean(L, true); }