diff --git a/res/scripts/stdcmd.lua b/res/scripts/stdcmd.lua index a2edd9b8..c5b832b7 100644 --- a/res/scripts/stdcmd.lua +++ b/res/scripts/stdcmd.lua @@ -187,3 +187,17 @@ console.add_command( " has been saved as "..file.resolve(filename)) end ) + +console.add_command( + "fragment.place file:str x:num~pos.x y:num~pos.y z:num~pos.z rotation:int=0", + "Place fragment to the world", + function(args, kwargs) + local filename = args[1] + local x = args[2] + local y = args[3] + local z = args[4] + local rotation = args[5] + local fragment = generation.load_fragment(filename) + fragment:place({x, y, z}, rotation) + end +) diff --git a/src/logic/scripting/lua/libs/libgeneration.cpp b/src/logic/scripting/lua/libs/libgeneration.cpp index ca97815c..034f6597 100644 --- a/src/logic/scripting/lua/libs/libgeneration.cpp +++ b/src/logic/scripting/lua/libs/libgeneration.cpp @@ -45,6 +45,7 @@ static int l_load_fragment(lua::State* L) { auto fragment = std::make_shared(); fragment->deserialize(map); + fragment->prepare(*content); return lua::newuserdata(L, std::move(fragment)); } diff --git a/src/logic/scripting/lua/usertypes/lua_type_voxelfragment.cpp b/src/logic/scripting/lua/usertypes/lua_type_voxelfragment.cpp index eb6a24ab..f123be6f 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_voxelfragment.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_voxelfragment.cpp @@ -4,6 +4,7 @@ #include "world/generator/VoxelFragment.hpp" #include "util/stringutil.hpp" +#include "world/Level.hpp" using namespace lua; @@ -20,8 +21,20 @@ static int l_crop(lua::State* L) { return 0; } +static int l_place(lua::State* L) { + if (auto fragment = touserdata(L, 1)) { + auto offset = tovec3(L, 2); + int rotation = tointeger(L, 3) & 0b11; + fragment->getFragment()->place( + *scripting::level->chunks, offset, rotation + ); + } + return 0; +} + static std::unordered_map methods { {"crop", lua::wrap}, + {"place", lua::wrap}, }; static int l_meta_tostring(lua::State* L) { diff --git a/src/world/generator/VoxelFragment.cpp b/src/world/generator/VoxelFragment.cpp index 832c1109..b6e65094 100644 --- a/src/world/generator/VoxelFragment.cpp +++ b/src/world/generator/VoxelFragment.cpp @@ -6,6 +6,7 @@ #include "data/dv_util.hpp" #include "content/Content.hpp" +#include "voxels/Chunks.hpp" #include "voxels/Block.hpp" #include "voxels/ChunksStorage.hpp" #include "voxels/VoxelsVolume.hpp" @@ -168,6 +169,29 @@ void VoxelFragment::prepare(const Content& content) { } } +void VoxelFragment::place( + Chunks& chunks, const glm::ivec3& offset, ubyte rotation +) { + auto& structVoxels = getRuntimeVoxels(); + for (int y = 0; y < size.y; y++) { + int sy = y + offset.y; + if (sy < 0 || sy >= CHUNK_H) { + continue; + } + for (int z = 0; z < size.z; z++) { + int sz = z + offset.z; + for (int x = 0; x < size.x; x++) { + int sx = x + offset.x; + const auto& structVoxel = + structVoxels[vox_index(x, y, z, size.x, size.z)]; + if (structVoxel.id) { + chunks.set(sx, sy, sz, structVoxel.id, structVoxel.state); + } + } + } + } +} + std::unique_ptr VoxelFragment::rotated(const Content& content) const { std::vector newVoxels(voxels.size()); diff --git a/src/world/generator/VoxelFragment.hpp b/src/world/generator/VoxelFragment.hpp index 95a5375b..701cac0e 100644 --- a/src/world/generator/VoxelFragment.hpp +++ b/src/world/generator/VoxelFragment.hpp @@ -10,6 +10,7 @@ inline constexpr int STRUCTURE_FORMAT_VERSION = 1; class Level; class Content; +class Chunks; class VoxelFragment : public Serializable { glm::ivec3 size; @@ -41,6 +42,11 @@ public: /// @param content world content void prepare(const Content& content); + /// @brief Place fragment to the world + /// @param offset target location + /// @param rotation rotation index + void place(Chunks& chunks, const glm::ivec3& offset, ubyte rotation); + /// @brief Create structure copy rotated 90 deg. clockwise std::unique_ptr rotated(const Content& content) const;