From 49defaeb3b2fd51f82f0d00a4f3dcf6964cc0e8f Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Mon, 2 Dec 2024 02:33:38 +0300 Subject: [PATCH] Add api to serialize and deserialize chunk to bytes --- src/logic/scripting/lua/libs/libworld.cpp | 99 ++++++++++++++++++++--- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 5422c873..b51bc7f8 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -1,16 +1,20 @@ #include -#include #include +#include +#include "api_lua.hpp" #include "assets/Assets.hpp" #include "assets/AssetsLoader.hpp" +#include "coders/gzip.hpp" #include "coders/json.hpp" #include "engine.hpp" -#include "files/files.hpp" #include "files/engine_paths.hpp" +#include "files/files.hpp" +#include "lighting/Lighting.hpp" +#include "voxels/Chunk.hpp" +#include "voxels/Chunks.hpp" #include "world/Level.hpp" #include "world/World.hpp" -#include "api_lua.hpp" using namespace scripting; namespace fs = std::filesystem; @@ -36,12 +40,12 @@ static int l_get_list(lua::State* L) { const auto& folder = worlds[i]; - auto root = json::parse(files::read_string(folder/fs::u8path("world.json"))); + auto root = + json::parse(files::read_string(folder / fs::u8path("world.json"))); const auto& versionMap = root["version"]; int versionMajor = versionMap["major"].asInteger(); int versionMinor = versionMap["minor"].asInteger(); - auto name = folder.filename().u8string(); lua::pushstring(L, name); lua::setfield(L, "name"); @@ -49,11 +53,11 @@ static int l_get_list(lua::State* L) { auto assets = engine->getAssets(); std::string icon = "world#" + name + ".icon"; if (!AssetsLoader::loadExternalTexture( - assets, - icon, - {worlds[i] / fs::path("icon.png"), - worlds[i] / fs::path("preview.png")} - )) { + assets, + icon, + {worlds[i] / fs::path("icon.png"), + worlds[i] / fs::path("preview.png")} + )) { icon = "gui/no_world_icon"; } lua::pushstring(L, icon); @@ -115,6 +119,76 @@ static int l_get_generator(lua::State* L) { return lua::pushstring(L, require_world_info().generator); } +static int l_get_chunk_data(lua::State* L) { + int x = (int)lua::tointeger(L, 1); + int y = (int)lua::tointeger(L, 2); + const auto& chunk = level->chunks->getChunk(x, y); + if (chunk->isEmpty()) { + return 0; + } + + bool compress = false; + if (lua::gettop(L) >= 3) { + compress = lua::toboolean(L, 3); + } + + if (compress) { + return lua::newuserdata( + L, gzip::compress(chunk->encode().get(), CHUNK_DATA_LEN) + ); + } + const auto chunk_data = chunk->encode(); + const std::vector data( + chunk_data.get(), chunk_data.get() + CHUNK_DATA_LEN + ); + return lua::newuserdata(L, data); +} + +static int l_set_chunk_data(lua::State* L) { + int x = (int)lua::tointeger(L, 1); + int y = (int)lua::tointeger(L, 2); + auto buffer = lua::touserdata(L, 3); + bool is_compressed = false; + if (lua::gettop(L) >= 4) { + is_compressed = lua::toboolean(L, 4); + } + auto chunk = level->chunks->getChunk(x, y); + if (is_compressed) { + auto data = + gzip::decompress(buffer->data().data(), buffer->data().size()); + chunk->decode(data.data()); + } else { + chunk->decode(buffer->data().data()); + } + chunk->updateHeights(); + level->lighting->buildSkyLight(x, y); + chunk->flags.modified = true; + level->lighting->onChunkLoaded(x, y, true); + + chunk = level->chunks->getChunk(x - 1, y); + if (chunk != nullptr) { + chunk->flags.modified = true; + level->lighting->onChunkLoaded(x - 1, y, true); + } + chunk = level->chunks->getChunk(x + 1, y); + if (chunk != nullptr) { + chunk->flags.modified = true; + level->lighting->onChunkLoaded(x + 1, y, true); + } + chunk = level->chunks->getChunk(x, y - 1); + if (chunk != nullptr) { + chunk->flags.modified = true; + level->lighting->onChunkLoaded(x, y - 1, true); + } + chunk = level->chunks->getChunk(x, y + 1); + if (chunk != nullptr) { + chunk->flags.modified = true; + level->lighting->onChunkLoaded(x, y + 1, true); + } + + return 1; +} + const luaL_Reg worldlib[] = { {"is_open", lua::wrap}, {"get_list", lua::wrap}, @@ -128,4 +202,7 @@ const luaL_Reg worldlib[] = { {"is_day", lua::wrap}, {"is_night", lua::wrap}, {"exists", lua::wrap}, - {NULL, NULL}}; + {"get_chunk_data", lua::wrap}, + {"set_chunk_data", lua::wrap}, + {NULL, NULL} +};