From 1be50c2e06079e66798bb8eb05b58da3a9301797 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Mon, 19 Aug 2024 21:36:30 +0300 Subject: [PATCH 1/3] libblock.raycast: Add argument to specify blocks to ignore during ray casting libentity.raycast: Add argument to specify blocks to ignore during ray casting Chunk::rayCast: Add argument to specify blocks to ignore during ray casting. On lua side filter blocks are passed as list of strings in form of "MOD:BLOCK_NAME" On C++ size filter blocks are std::set of blockid_t --- src/logic/scripting/lua/libblock.cpp | 24 ++++++++++++++++--- src/logic/scripting/lua/libentity.cpp | 33 ++++++++++++++++++++++----- src/voxels/Chunks.cpp | 7 ++++-- src/voxels/Chunks.hpp | 4 +++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index f346098a..342f7899 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -353,13 +353,30 @@ static int l_raycast(lua::State* L) { auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); auto maxDistance = lua::tonumber(L, 3); + std::set filteredBlocks {}; + if (lua::gettop(L) >= 5) { + if (lua::istable(L, 5)) { + int addLen = lua::objlen(L, 5); + for (int i = 0; i < addLen; i++) { + lua::rawgeti(L, i + 1, 5); + auto blockName = std::string(lua::tostring(L, -1)); + Block* block = content->blocks.find(blockName); + if (block != nullptr) { + filteredBlocks.insert(block->rt.id); + } + lua::pop(L); + } + } else { + throw std::runtime_error("table expected for filter"); + } + } glm::vec3 end; glm::ivec3 normal; glm::ivec3 iend; if (auto voxel = level->chunks->rayCast( - start, dir, maxDistance, end, normal, iend + start, dir, maxDistance, end, normal, iend, filteredBlocks )) { - if (lua::gettop(L) >= 4) { + if (lua::gettop(L) >= 4 && !lua::isnil(L, 4)) { lua::pushvalue(L, 4); } else { lua::createtable(L, 0, 5); @@ -452,4 +469,5 @@ const luaL_Reg blocklib[] = { {"raycast", lua::wrap}, {"compose_state", lua::wrap}, {"decompose_state", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index f952a83d..1d21c6ef 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -8,6 +8,7 @@ #include "objects/rigging.hpp" #include "physics/Hitbox.hpp" #include "voxels/Chunks.hpp" +#include "voxels/Block.hpp" #include "window/Camera.hpp" using namespace scripting; @@ -118,7 +119,25 @@ static int l_raycast(lua::State* L) { auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); auto maxDistance = lua::tonumber(L, 3); - auto ignore = lua::tointeger(L, 4); + auto ignoreEntityId = lua::tointeger(L, 4); + std::set filteredBlocks {}; + if (lua::gettop(L) >= 6) { + if (lua::istable(L, 6)) { + int addLen = lua::objlen(L, 6); + for (int i = 0; i < addLen; i++) { + lua::rawgeti(L, i + 1, 6); + auto blockName = std::string(lua::tostring(L, -1)); + Block* block = content->blocks.find(blockName); + if (block != nullptr) { + filteredBlocks.insert(block->rt.id); + } + lua::pop(L); + } + } else { + throw std::runtime_error("table expected for filter"); + } + } + glm::vec3 end; glm::ivec3 normal; glm::ivec3 iend; @@ -126,13 +145,14 @@ static int l_raycast(lua::State* L) { blockid_t block = BLOCK_VOID; if (auto voxel = level->chunks->rayCast( - start, dir, maxDistance, end, normal, iend + start, dir, maxDistance, end, normal, iend, filteredBlocks )) { maxDistance = glm::distance(start, end); block = voxel->id; } - if (auto ray = level->entities->rayCast(start, dir, maxDistance, ignore)) { - if (lua::gettop(L) >= 5) { + if (auto ray = + level->entities->rayCast(start, dir, maxDistance, ignoreEntityId)) { + if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) { lua::pushvalue(L, 5); } else { lua::createtable(L, 0, 6); @@ -157,7 +177,7 @@ static int l_raycast(lua::State* L) { lua::setfield(L, "entity"); return 1; } else if (block != BLOCK_VOID) { - if (lua::gettop(L) >= 5) { + if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) { lua::pushvalue(L, 5); } else { lua::createtable(L, 0, 5); @@ -194,4 +214,5 @@ const luaL_Reg entitylib[] = { {"get_all_in_box", lua::wrap}, {"get_all_in_radius", lua::wrap}, {"raycast", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 1dbfd5a1..d22ec3cc 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -414,7 +414,8 @@ voxel* Chunks::rayCast( float maxDist, glm::vec3& end, glm::ivec3& norm, - glm::ivec3& iend + glm::ivec3& iend, + std::set filter ) { float px = start.x; float py = start.y; @@ -454,8 +455,10 @@ voxel* Chunks::rayCast( if (voxel == nullptr) { return nullptr; } + const auto& def = indices->blocks.require(voxel->id); - if (def.selectable) { + if ((filter.empty() && def.selectable) || + (!filter.empty() && filter.find(def.rt.id) == filter.end())) { end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index d17cf9b9..0d3e07e4 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "typedefs.hpp" @@ -93,7 +94,8 @@ public: float maxLength, glm::vec3& end, glm::ivec3& norm, - glm::ivec3& iend + glm::ivec3& iend, + std::set filter = {} ); glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist); From a48d54aa27b090d5e8627a04b7cdbba12be4089e Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 15:33:29 +0300 Subject: [PATCH 2/3] block.raycast/entity.raycast: Updated docs to reflect changes --- doc/en/scripting/builtins/libblock.md | 7 ++++++- doc/en/scripting/builtins/libentities.md | 2 +- doc/ru/scripting/builtins/libblock.md | 7 ++++++- doc/ru/scripting/builtins/libentities.md | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 2c2c0182..1d11417c 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -120,12 +120,17 @@ block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: tab endpoint: vec3, -- point of the ray hit point iendpoint: vec3, -- position of the block hit by the ray length: number, -- ray length - normal: vec3 -- normal vector of the surface hit by the ray + normal: vec3, -- normal vector of the surface hit by the ray + [optional] dest: table, -- table where result will be written to instead of function return + [optional] filter: table -- list of block names that are "transparent" for ray } or nil ``` Casts a ray from the start point in the direction of *dir*. Max_distance specifies the maximum ray length. +Argument `filter` can be used to tell ray what blocks can be skipped(passed through) during ray-casting. +To use filter `dest` argument must be filled with some value(can be nil), it's done for backwards compatability + The function returns a table with the results or nil if the ray does not hit any block. The result will use the destination table instead of creating a new one if the optional argument specified. diff --git a/doc/en/scripting/builtins/libentities.md b/doc/en/scripting/builtins/libentities.md index bd50c0e1..c0a5d260 100644 --- a/doc/en/scripting/builtins/libentities.md +++ b/doc/en/scripting/builtins/libentities.md @@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array ```lua entities.raycast(start: vec3, dir: vec3, max_distance: number, - ignore: int, [optional] destination: table) -> table or nil + ignore: int, [optional] destination: table, [optional] filter: table) -> table or nil ``` The function is an extended version of [block.raycast](libblock.md#raycast). Returns a table with the results if the ray touches a block or entity. diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index d4d28a28..77633c17 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -65,12 +65,17 @@ block.raycast(start: vec3, dir: vec3, max_distance: number, [опциональ endpoint: vec3, -- точка касания луча iendpoint: vec3, -- позиция блока, которого касается луч length: number, -- длина луча - normal: vec3 -- вектор нормали поверхности, которой касается луч + normal: vec3, -- вектор нормали поверхности, которой касается луч + [optional] dest: table, -- таблица куда будет записан результат вместо возврата из функции + [optional] filter: table -- массив имён блоков которые "прозрачны" для луча } или nil ``` Бросает луч из точки start в направлении dir. Max_distance указывает максимальную длину луча. +Аргумент `filter` позволяет указать какие блоки являются "прозрачными" для луча, прим.: {"base:glass","base:water"}. +Для использования агрумент `dest` нужно чем-то заполнить(можно nil), это сделано для обратной совместимости + Функция возвращает таблицу с результатами или nil, если луч не касается блока. Для результата будет использоваться целевая (dest) таблица вместо создания новой, если указан опциональный аргумент. diff --git a/doc/ru/scripting/builtins/libentities.md b/doc/ru/scripting/builtins/libentities.md index ebb23497..93275e5b 100644 --- a/doc/ru/scripting/builtins/libentities.md +++ b/doc/ru/scripting/builtins/libentities.md @@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array ```lua entities.raycast(start: vec3, dir: vec3, max_distance: number, - ignore: int, [optional] destination: table) -> table или nil + ignore: int, [optional] destination: table, [optional] filter: table) -> table или nil ``` Функция является расширенным вариантом [block.raycast](libblock.md#raycast). Возвращает таблицу с результатами если луч касается блока, либо сущности. From 615dd239136fbe5bbe4e60cda13d92c5648c63a5 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 18:17:11 +0300 Subject: [PATCH 3/3] block.raycast: fix documentation --- doc/en/scripting/builtins/libblock.md | 4 +--- doc/ru/scripting/builtins/libblock.md | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 1d11417c..87176e20 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -115,14 +115,12 @@ Set specified bits. ## Raycast ```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table) -> { +block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table, [optional] filter: table) -> { block: int, -- block id endpoint: vec3, -- point of the ray hit point iendpoint: vec3, -- position of the block hit by the ray length: number, -- ray length normal: vec3, -- normal vector of the surface hit by the ray - [optional] dest: table, -- table where result will be written to instead of function return - [optional] filter: table -- list of block names that are "transparent" for ray } or nil ``` diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index 77633c17..150e776e 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -60,14 +60,12 @@ block.get_picking_item(id: int) -> int ### Raycast ```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table) -> { +block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table, [опционально] filter: table) -> { block: int, -- id блока endpoint: vec3, -- точка касания луча iendpoint: vec3, -- позиция блока, которого касается луч length: number, -- длина луча normal: vec3, -- вектор нормали поверхности, которой касается луч - [optional] dest: table, -- таблица куда будет записан результат вместо возврата из функции - [optional] filter: table -- массив имён блоков которые "прозрачны" для луча } или nil ```