From 2d7d03efbb7498b5a9d117536aecd6234055cd19 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 22 Aug 2024 20:35:41 +0300 Subject: [PATCH] add structures (WIP) --- res/scripts/stdcmd.lua | 17 ++++++++ src/data/dynamic_util.hpp | 25 ++++++++++++ src/logic/scripting/lua/libgeneration.cpp | 26 ++++++++++++ src/world/generator/Structure.cpp | 50 +++++++++++++++++++++++ src/world/generator/Structure.hpp | 27 ++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 src/world/generator/Structure.cpp create mode 100644 src/world/generator/Structure.hpp diff --git a/res/scripts/stdcmd.lua b/res/scripts/stdcmd.lua index 61dccba8..9d05a3b5 100644 --- a/res/scripts/stdcmd.lua +++ b/res/scripts/stdcmd.lua @@ -149,3 +149,20 @@ console.add_command( end end ) + +console.add_command( + "structure.save x:int y:int z:int w:int h:int d:int name:str='untitled'", + "Save structure", + function(args, kwargs) + local x = args[1] + local y = args[2] + local z = args[3] + + local w = args[4] + local h = args[5] + local d = args[6] + + local name = args[7] + generation.save_structure({x, y, z}, {x+w, y+h, z+d}, name..'.vox', false) + end +) diff --git a/src/data/dynamic_util.hpp b/src/data/dynamic_util.hpp index c8a82ce9..836eb21f 100644 --- a/src/data/dynamic_util.hpp +++ b/src/data/dynamic_util.hpp @@ -38,6 +38,20 @@ namespace dynamic { } } + /// TODO: remove raw pointer overloads + template + void get_vec( + const dynamic::Map* root, + const std::string& name, + glm::vec& vec + ) { + if (const auto& list = root->list(name)) { + for (size_t i = 0; i < n; i++) { + vec[i] = list->integer(i); + } + } + } + template void get_vec( const dynamic::List_sptr& root, size_t index, glm::vec& vec @@ -49,6 +63,17 @@ namespace dynamic { } } + template + void get_vec( + const dynamic::List_sptr& root, size_t index, glm::vec& vec + ) { + if (const auto& list = root->list(index)) { + for (size_t i = 0; i < n; i++) { + vec[i] = list->integer(i); + } + } + } + template void get_mat( const dynamic::Map_sptr& root, diff --git a/src/logic/scripting/lua/libgeneration.cpp b/src/logic/scripting/lua/libgeneration.cpp index c9b55e1d..106ddbb1 100644 --- a/src/logic/scripting/lua/libgeneration.cpp +++ b/src/logic/scripting/lua/libgeneration.cpp @@ -1,4 +1,30 @@ #include "api_lua.hpp" +#include "files/files.hpp" +#include "files/util.hpp" +#include "coders/binary_json.hpp" +#include "world/Level.hpp" +#include "world/generator/Structure.hpp" + +using namespace scripting; + +static int l_save_structure(lua::State* L) { + auto pointA = lua::tovec<3>(L, 1); + auto pointB = lua::tovec<3>(L, 2); + auto filename = lua::require_string(L, 3); + if (!files::is_valid_name(filename)) { + throw std::runtime_error("invalid file name"); + } + bool saveEntities = lua::toboolean(L, 4); + + auto structure = Structure::create(level, pointA, pointB, saveEntities); + auto map = structure->serialize(); + + auto bytes = json::to_binary(map.get()); + files::write_bytes(fs::u8path(filename), bytes.data(), bytes.size()); + return 0; +} + const luaL_Reg generationlib[] = { + {"save_structure", lua::wrap}, {NULL, NULL}}; diff --git a/src/world/generator/Structure.cpp b/src/world/generator/Structure.cpp new file mode 100644 index 00000000..0ce55c67 --- /dev/null +++ b/src/world/generator/Structure.cpp @@ -0,0 +1,50 @@ +#include "Structure.hpp" + +#include + +#include "data/dynamic.hpp" +#include "data/dynamic_util.hpp" +#include "voxels/ChunksStorage.hpp" +#include "voxels/VoxelsVolume.hpp" +#include "world/Level.hpp" + +std::unique_ptr Structure::create( + Level* level, const glm::ivec3& a, const glm::ivec3& b, bool entities +) { + auto start = glm::min(a, b); + auto size = glm::abs(a - b); + + VoxelsVolume volume(size.x, size.y, size.z); + level->chunksStorage->getVoxels(&volume); + + auto volVoxels = volume.getVoxels(); + std::vector voxels(size.x*size.y*size.z); + std::memcpy(voxels.data(), volVoxels, sizeof(voxel) * voxels.size()); + + return std::make_unique(size, std::move(voxels)); +} + +std::unique_ptr Structure::serialize() const { + auto root = std::make_unique(); + root->put("version", STRUCTURE_FORMAT_VERSION); + root->put("size", dynamic::to_value(size)); + + auto& voxelsArr = root->putList("voxels"); + for (size_t i = 0; i < voxels.size(); i++) { + voxelsArr.put(voxels[i].id); + voxelsArr.put(blockstate2int(voxels[i].state)); + } + return root; +} + +void Structure::deserialize(dynamic::Map* src) { + size = glm::ivec3(); + dynamic::get_vec(src, "size", size); + voxels.resize(size.x*size.y*size.z); + + auto voxelsArr = src->list("voxels"); + for (size_t i = 0; i < size.x*size.y*size.z; i++) { + voxels[i].id = voxelsArr->integer(i * 2); + voxels[i].state = int2blockstate(voxelsArr->integer(i * 2 + 1)); + } +} diff --git a/src/world/generator/Structure.hpp b/src/world/generator/Structure.hpp new file mode 100644 index 00000000..93d93a4d --- /dev/null +++ b/src/world/generator/Structure.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include "interfaces/Serializable.hpp" +#include "voxels/voxel.hpp" + +inline constexpr int STRUCTURE_FORMAT_VERSION = 1; + +class Level; + +struct Structure : public Serializable { + glm::ivec3 size; + std::vector voxels; + + Structure() : size() {} + + Structure(glm::ivec3 size, std::vector voxels) + : size(size), voxels(std::move(voxels)) {} + + std::unique_ptr serialize() const override; + void deserialize(dynamic::Map* src) override; + + static std::unique_ptr create( + Level* level, const glm::ivec3& a, const glm::ivec3& b, bool entities); +};