add metadata to chunk data used in world.get/set_chunk_data

This commit is contained in:
MihailRis 2025-01-12 01:47:07 +03:00
parent 077de25acc
commit c5fa6935a6

View File

@ -7,6 +7,7 @@
#include "coders/compression.hpp" #include "coders/compression.hpp"
#include "coders/gzip.hpp" #include "coders/gzip.hpp"
#include "coders/json.hpp" #include "coders/json.hpp"
#include "coders/byte_utils.hpp"
#include "coders/rle.hpp" #include "coders/rle.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
#include "files/engine_paths.hpp" #include "files/engine_paths.hpp"
@ -123,12 +124,10 @@ static int l_get_generator(lua::State* L) {
return lua::pushstring(L, require_world_info().generator); return lua::pushstring(L, require_world_info().generator);
} }
static std::vector<ubyte> prepare_chunk_data(const Chunk& chunk, bool compress) { static std::vector<ubyte> prepare_chunk_data(const Chunk& chunk) {
auto data = chunk.encode(); auto data = chunk.encode();
std::vector<ubyte> chunkData; /// world.get_chunk_data is only available in the main Lua state
if (compress) {
// world.get_chunk_data is only available in the main Lua state
static util::Buffer<ubyte> rleBuffer; static util::Buffer<ubyte> rleBuffer;
if (rleBuffer.size() < CHUNK_DATA_LEN * 2) { if (rleBuffer.size() < CHUNK_DATA_LEN * 2) {
rleBuffer = util::Buffer<ubyte>(CHUNK_DATA_LEN * 2); rleBuffer = util::Buffer<ubyte>(CHUNK_DATA_LEN * 2);
@ -139,23 +138,15 @@ static std::vector<ubyte> prepare_chunk_data(const Chunk& chunk, bool compress)
const auto gzipCompressedData = gzip::compress( const auto gzipCompressedData = gzip::compress(
rleBuffer.data(), rleCompressedSize rleBuffer.data(), rleCompressedSize
); );
auto tmp = dataio::h2le(rleCompressedSize); auto metadataBytes = chunk.blocksMetadata.serialize();
chunkData.reserve(gzipCompressedData.size() + sizeof(tmp));
chunkData.insert( ByteBuilder builder(2 + 8 + gzipCompressedData.size() + metadataBytes.size());
chunkData.begin() + 0, (char*)&tmp, ((char*)&tmp) + sizeof(tmp) builder.putInt16(0); // header
); builder.putInt32(gzipCompressedData.size());
chunkData.insert( builder.put(gzipCompressedData.data(), gzipCompressedData.size());
chunkData.begin() + sizeof(tmp), builder.putInt32(metadataBytes.size());
gzipCompressedData.data(), builder.put(metadataBytes.data(), metadataBytes.size());
gzipCompressedData.data() + gzipCompressedData.size() return builder.build();
);
} else {
chunkData.reserve(CHUNK_DATA_LEN);
chunkData.insert(
chunkData.begin(), data.get(), data.get() + CHUNK_DATA_LEN
);
}
return chunkData;
} }
static int l_get_chunk_data(lua::State* L) { 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); lua::pushnil(L);
return 0; return 0;
} }
bool compress = true; auto chunkData = prepare_chunk_data(*chunk);
if (lua::gettop(L) >= 3) {
compress = lua::toboolean(L, 3);
}
auto chunkData = prepare_chunk_data(*chunk, compress);
return lua::newuserdata<lua::LuaBytearray>(L, std::move(chunkData)); return lua::newuserdata<lua::LuaBytearray>(L, std::move(chunkData));
} }
@ -178,33 +165,29 @@ static int l_set_chunk_data(lua::State* L) {
int x = static_cast<int>(lua::tointeger(L, 1)); int x = static_cast<int>(lua::tointeger(L, 1));
int y = static_cast<int>(lua::tointeger(L, 2)); int y = static_cast<int>(lua::tointeger(L, 2));
auto buffer = lua::touserdata<lua::LuaBytearray>(L, 3); auto buffer = lua::touserdata<lua::LuaBytearray>(L, 3);
bool isCompressed = true;
if (lua::gettop(L) >= 4) {
isCompressed = lua::toboolean(L, 4);
}
auto chunk = level->chunks->getChunk(x, y); auto chunk = level->chunks->getChunk(x, y);
if (chunk == nullptr) { if (chunk == nullptr) {
return 0; return 0;
} }
if (isCompressed) {
std::vector<ubyte>& rawData = buffer->data(); std::vector<ubyte>& rawData = buffer->data();
size_t gzipDecompressedSize = dataio::le2h(*(size_t*)(rawData.data()));
auto rleData = compression::decompress( ByteReader reader(rawData.data(), rawData.size());
rawData.data() + sizeof(gzipDecompressedSize),
buffer->data().size() - sizeof(gzipDecompressedSize), uint16_t header = reader.getInt16();
gzipDecompressedSize, size_t gzipCompressedSize = reader.getInt32();
compression::Method::GZIP
); auto rleData = gzip::decompress(reader.pointer(), gzipCompressedSize);
auto data = compression::decompress( reader.skip(gzipCompressedSize);
rleData.get(),
gzipDecompressedSize, /// world.get_chunk_data is only available in the main Lua state
CHUNK_DATA_LEN, static util::Buffer<ubyte> voxelData (CHUNK_DATA_LEN);
compression::Method::EXTRLE16 extrle::decode16(rleData.data(), rleData.size(), voxelData.data());
); chunk->decode(voxelData.data());
chunk->decode(data.get());
} else { size_t metadataSize = reader.getInt32();
chunk->decode(buffer->data().data()); chunk->blocksMetadata.deserialize(reader.pointer(), metadataSize);
} reader.skip(metadataSize);
chunk->setModifiedAndUnsaved(); chunk->setModifiedAndUnsaved();
chunk->updateHeights(); chunk->updateHeights();
@ -233,7 +216,6 @@ static int l_set_chunk_data(lua::State* L) {
} }
} }
} }
return lua::pushboolean(L, true); return lua::pushboolean(L, true);
} }