Add support for group:supported_node

* Add support for `group:supported_node` to CORE/mcl_attached.
  Supported nodes are nodes that can be placed on any node that does not
  have the `drawtype = "airlike"` attribute.
* Copy the `drop_attached_node()` function from minetest/builtin, so
  that the override function provides the same behavior when nodes drop.
* Add comments to CORE/mcl_attached and to the functions defined in it.
* Add more local aliases for global minetest.* functions.
* If the original function returns true, it is not necessary anymore
  to perform more tests and the override function can simply return true
  immediately.
This commit is contained in:
kabou 2022-03-19 00:58:29 +01:00
parent 81a1b9973a
commit 8518ce2c19

View File

@ -1,29 +1,93 @@
-- Overrides the builtin minetest.check_single_for_falling.
-- We need to do this in order to handle nodes in mineclone specific groups
-- "supported_node" and "attached_node_facedir".
--
-- Nodes in group "supported_node" can be placed on any node that does not
-- have the "airlike" drawtype. Carpets are an example of this type.
local vector = vector local vector = vector
local facedir_to_dir = minetest.facedir_to_dir local facedir_to_dir = minetest.facedir_to_dir
local get_item_group = minetest.get_item_group local get_item_group = minetest.get_item_group
local remove_node = minetest.remove_node local remove_node = minetest.remove_node
local get_node = minetest.get_node local get_node = minetest.get_node
local get_meta = minetest.get_meta
local registered_nodes = minetest.registered_nodes
local get_node_drops = minetest.get_node_drops
local add_item = minetest.add_item
-- drop_attached_node(p)
--
-- This function is copied verbatim from minetest/builtin/game/falling.lua
-- We need this to do the exact same dropping node handling in our override
-- minetest.check_single_for_falling() function as in the builtin function.
--
local function drop_attached_node(p)
local n = get_node(p)
local drops = get_node_drops(n, "")
local def = registered_nodes[n.name]
if def and def.preserve_metadata then
local oldmeta = get_meta(p):to_table().fields
-- Copy pos and node because the callback can modify them.
local pos_copy = vector.new(p)
local node_copy = {name=n.name, param1=n.param1, param2=n.param2}
local drop_stacks = {}
for k, v in pairs(drops) do
drop_stacks[k] = ItemStack(v)
end
drops = drop_stacks
def.preserve_metadata(pos_copy, node_copy, oldmeta, drops)
end
if def and def.sounds and def.sounds.fall then
core.sound_play(def.sounds.fall, {pos = p}, true)
end
remove_node(p)
for _, item in pairs(drops) do
local pos = {
x = p.x + math.random()/2 - 0.25,
y = p.y + math.random()/2 - 0.25,
z = p.z + math.random()/2 - 0.25,
}
add_item(pos, item)
end
end
-- minetest.check_single_for_falling(pos)
--
-- * causes an unsupported `group:falling_node` node to fall and causes an
-- unattached `group:attached_node` or `group:attached_node_facedir` node
-- or unsupported `group:supported_node` to drop.
-- * does not spread these updates to neighbours.
--
-- Returns true if the node at <pos> has spawned a falling node or has been
-- dropped as item(s).
--
local original_function = minetest.check_single_for_falling local original_function = minetest.check_single_for_falling
function minetest.check_single_for_falling(pos) function minetest.check_single_for_falling(pos)
local ret_o = original_function(pos) if original_function(pos) then
local ret = false return true
local node = minetest.get_node(pos) end
local node = get_node(pos)
if get_item_group(node.name, "attached_node_facedir") ~= 0 then if get_item_group(node.name, "attached_node_facedir") ~= 0 then
local dir = facedir_to_dir(node.param2) local dir = facedir_to_dir(node.param2)
if dir then if dir then
if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then
remove_node(pos) drop_attached_node(pos)
local drops = minetest.get_node_drops(node.name, "") return true
for dr=1, #drops do
minetest.add_item(pos, drops[dr])
end
ret = true
end end
end end
end end
return ret_o or ret
end if get_item_group(node.name, "supported_node") ~= 0 then
local def = registered_nodes[get_node(vector.offset(pos, 0, -1, 0)).name]
if def and def.drawtype == "airlike" then
drop_attached_node(pos)
return true
end
end
return false
end