From e40417f6875015119ed9a292f53ee0afc912209c Mon Sep 17 00:00:00 2001 From: grorp Date: Fri, 1 Mar 2024 17:12:13 +0100 Subject: [PATCH] Allow giving "pointabilities" to Lua raycasts (#14390) --- doc/lua_api.md | 23 ++++++++------- games/devtest/mods/unittests/init.lua | 1 + games/devtest/mods/unittests/raycast.lua | 36 ++++++++++++++++++++++++ src/script/lua_api/l_env.cpp | 6 +++- 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 games/devtest/mods/unittests/raycast.lua diff --git a/doc/lua_api.md b/doc/lua_api.md index 2eefacc08..6dbc58cb0 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6202,13 +6202,16 @@ Environment access * Returns the position of the blocking node when `false` * `pos1`: First position * `pos2`: Second position -* `minetest.raycast(pos1, pos2, objects, liquids)`: returns `Raycast` +* `minetest.raycast(pos1, pos2, objects, liquids, pointabilities)`: returns `Raycast` * Creates a `Raycast` object. * `pos1`: start of the ray * `pos2`: end of the ray * `objects`: if false, only nodes will be returned. Default is `true`. * `liquids`: if false, liquid nodes (`liquidtype ~= "none"`) won't be returned. Default is `false`. + * `pointabilities`: Allows overriding the `pointable` property of + nodes and objects. Uses the same format as the `pointabilities` property + of item definitions. Default is `nil`. * `minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,algorithm)` * returns table containing path that can be walked on * returns a table of 3D points representing a path from `pos1` to `pos2` or @@ -8932,16 +8935,16 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and -- even those for which `pointable = false` pointabilities = { - nodes = { - ["default:stone"] = "blocking", - ["group:leaves"] = false, - }, - objects = { - ["modname:entityname"] = true, - ["group:ghosty"] = true, -- (an armor group) - } + nodes = { + ["default:stone"] = "blocking", + ["group:leaves"] = false, + }, + objects = { + ["modname:entityname"] = true, + ["group:ghosty"] = true, -- (an armor group) + }, }, - -- Contains lists to override the `pointable` property of pointed nodes and objects. + -- Contains lists to override the `pointable` property of nodes and objects. -- The index can be a node/entity name or a group with the prefix `"group:"`. -- (For objects `armor_groups` are used and for players the entity name is irrelevant.) -- If multiple fields fit, the following priority order is applied: diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua index edba2c3d2..f048b7aa6 100644 --- a/games/devtest/mods/unittests/init.lua +++ b/games/devtest/mods/unittests/init.lua @@ -182,6 +182,7 @@ dofile(modpath .. "/get_version.lua") dofile(modpath .. "/itemstack_equals.lua") dofile(modpath .. "/content_ids.lua") dofile(modpath .. "/metadata.lua") +dofile(modpath .. "/raycast.lua") -------------- diff --git a/games/devtest/mods/unittests/raycast.lua b/games/devtest/mods/unittests/raycast.lua new file mode 100644 index 000000000..08d6a1120 --- /dev/null +++ b/games/devtest/mods/unittests/raycast.lua @@ -0,0 +1,36 @@ +local function raycast_with_pointabilities(start_pos, end_pos, pointabilities) + local ray = core.raycast(start_pos, end_pos, nil, nil, pointabilities) + for hit in ray do + if hit.type == "node" then + return hit.under + end + end + return nil +end + +local function test_raycast_pointabilities(player, pos1) + local pos2 = pos1:offset(0, 0, 1) + local pos3 = pos1:offset(0, 0, 2) + + local oldnode1 = core.get_node(pos1) + local oldnode2 = core.get_node(pos2) + local oldnode3 = core.get_node(pos3) + core.swap_node(pos1, {name = "air"}) + core.swap_node(pos2, {name = "testnodes:not_pointable"}) + core.swap_node(pos3, {name = "testnodes:pointable"}) + + local p = nil + assert(raycast_with_pointabilities(pos1, pos3, p) == pos3) + + p = core.registered_items["testtools:blocked_pointing_staff"].pointabilities + assert(raycast_with_pointabilities(pos1, pos3, p) == nil) + + p = core.registered_items["testtools:ultimate_pointing_staff"].pointabilities + assert(raycast_with_pointabilities(pos1, pos3, p) == pos2) + + core.swap_node(pos1, oldnode1) + core.swap_node(pos2, oldnode2) + core.swap_node(pos3, oldnode3) +end + +unittests.register("test_raycast_pointabilities", test_raycast_pointabilities, {map=true}) diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 39f36a31a..c6a427e48 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -177,6 +177,7 @@ int LuaRaycast::create_object(lua_State *L) bool objects = true; bool liquids = false; + std::optional pointabilities = std::nullopt; v3f pos1 = checkFloatPos(L, 1); v3f pos2 = checkFloatPos(L, 2); @@ -186,9 +187,12 @@ int LuaRaycast::create_object(lua_State *L) if (lua_isboolean(L, 4)) { liquids = readParam(L, 4); } + if (lua_istable(L, 5)) { + pointabilities = read_pointabilities(L, 5); + } LuaRaycast *o = new LuaRaycast(core::line3d(pos1, pos2), - objects, liquids, std::nullopt); + objects, liquids, pointabilities); *(void **) (lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className);