From c9257ec127ad86a289582317f6625b4251fd703e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 18 Jul 2024 08:41:16 +0300 Subject: [PATCH] add block.place(...), block.destruct(...) --- doc/en/scripting/builtins/libblock.md | 11 ++++- doc/ru/scripting/builtins/libblock.md | 9 ++++ .../base/scripts/components/falling_block.lua | 2 +- src/logic/scripting/lua/libblock.cpp | 42 +++++++++++++++++++ src/logic/scripting/scripting.cpp | 4 +- 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 1b095afc..9516524c 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -20,8 +20,17 @@ block.get(x: int, y: int, z: int) -> int -- Used to save complete block information. block.get_states(x: int, y: int, z: int) -> int --- Set block with specified integer ID and state (default - 0) at specified position. +-- Set block with given integer ID and state (default - 0) at given position. block.set(x: int, y: int, z: int, id: int, states: int) + +-- Places a block with a given integer id and state (default - 0) at given position. +-- on behalf of the player, calling the on_placed event. +-- playerid is optional +block.place(x: int, y: int, z: int, id: int, states: int, [optional] playerid: int) + +-- Breaks a block at the given coordinates on behalf of the player, triggering the on_broken event. +-- playerid is optional +block.destruct(x: int, y: int, z: int, playerid: int) ``` > [!WARNING] diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index 8e3926d8..55de7aeb 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -22,6 +22,15 @@ block.get_states(x: int, y: int, z: int) -> int -- Устанавливает блок с заданным числовым id и состоянием (0 - по-умолчанию) на заданных координатах. block.set(x: int, y: int, z: int, id: int, states: int) + +-- Устанавливает блок с заданным числовым id и состоянием (0 - по-умолчанию) на заданных координатах +-- от лица игрока, вызывая событие on_placed. +-- playerid не является обязательным +block.place(x: int, y: int, z: int, id: int, states: int, [optional] playerid: int) + +-- Ломает блок на заданных координатах от лица игрока, вызывая событие on_broken. +-- playerid не является обязательным +block.destruct(x: int, y: int, z: int, playerid: int) ``` > [!WARNING] diff --git a/res/content/base/scripts/components/falling_block.lua b/res/content/base/scripts/components/falling_block.lua index c5a91a79..b5623b12 100644 --- a/res/content/base/scripts/components/falling_block.lua +++ b/res/content/base/scripts/components/falling_block.lua @@ -23,7 +23,7 @@ function on_grounded() local iy = math.floor(pos[2]) local iz = math.floor(pos[3]) if block.is_replaceable_at(ix, iy, iz) then - block.set(ix, iy, iz, block.index(blockid)) + block.place(ix, iy, iz, block.index(blockid), 0) else local picking_item = block.get_picking_item(block.index(blockid)) local drop = entities.spawn("base:drop", pos, {base__drop={id=picking_item, count=1}}) diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index 660d8f3c..7687e2ee 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -8,6 +8,7 @@ #include "../../../lighting/Lighting.hpp" #include "../../../content/Content.hpp" #include "../../../logic/BlocksController.hpp" +#include "../../../logic/LevelController.hpp" using namespace scripting; @@ -307,6 +308,45 @@ static int l_get_picking_item(lua::State* L) { return 0; } +static int l_place(lua::State* L) { + auto x = lua::tointeger(L, 1); + auto y = lua::tointeger(L, 2); + auto z = lua::tointeger(L, 3); + auto id = lua::tointeger(L, 4); + auto state = lua::tointeger(L, 5); + auto playerid = lua::gettop(L) >= 6 ? lua::tointeger(L, 6) : -1; + if (static_cast(id) >= indices->blocks.count()) { + return 0; + } + if (!level->chunks->get(x, y, z)) { + return 0; + } + const auto def = level->content->getIndices()->blocks.get(id); + if (def == nullptr) { + throw std::runtime_error("there is no block with index "+std::to_string(id)); + } + auto player = level->getObject(playerid); + controller->getBlocksController()->placeBlock( + player ? player.get() : nullptr, def, int2blockstate(state), x, y, z); + return 0; +} + +static int l_destruct(lua::State* L) { + auto x = lua::tointeger(L, 1); + auto y = lua::tointeger(L, 2); + auto z = lua::tointeger(L, 3); + auto playerid = lua::gettop(L) >= 4 ? lua::tointeger(L, 4) : -1; + auto voxel = level->chunks->get(x, y, z); + if (voxel == nullptr) { + return 0; + } + const auto def = level->content->getIndices()->blocks.get(voxel->id); + auto player = level->getObject(playerid); + controller->getBlocksController()->breakBlock( + player ? player.get() : nullptr, def, x, y, z); + return 0; +} + static int l_raycast(lua::State* L) { auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); @@ -368,6 +408,8 @@ const luaL_Reg blocklib [] = { {"get_hitbox", lua::wrap}, {"get_rotation_profile", lua::wrap}, {"get_picking_item", lua::wrap}, + {"place", lua::wrap}, + {"destruct", lua::wrap}, {"raycast", lua::wrap}, {NULL, NULL} }; diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 06205b1e..3b46455d 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -216,7 +216,7 @@ void scripting::on_block_placed(Player* player, const Block* block, int x, int y std::string name = block->name + ".placed"; lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { lua::pushivec3(L, x, y, z); - lua::pushinteger(L, player->getId()); + lua::pushinteger(L, player ? player->getId() : -1); return 4; }); auto world_event_args = [block, x, y, z, player] (lua::State* L) { @@ -237,7 +237,7 @@ void scripting::on_block_broken(Player* player, const Block* block, int x, int y if (block->rt.funcsset.onbroken) { lua::emit_event(lua::get_main_thread(), name, [x, y, z, player] (auto L) { lua::pushivec3(L, x, y, z); - lua::pushinteger(L, player->getId()); + lua::pushinteger(L, player ? player->getId() : -1); return 4; }); }