diff --git a/GROUPS.md b/GROUPS.md index 8286b29bc..8ff75bbda 100644 --- a/GROUPS.md +++ b/GROUPS.md @@ -56,6 +56,7 @@ Please read to learn how digging times * `no_eat_delay=1`: Only for foodstuffs. When eating this, all eating delays are ignored. * `can_eat_when_full=1`: Only for foodstuffs. This item can be eaten when the user has a full hunger bar * `attached_node_facedir=1`: Like `attached_node`, but for facedir nodes +* `supported_node=1`: Like `attached_node`, but can be placed on any nodes that do not have the `drawtype="airlike"` attribute. * `cauldron`: Cauldron. 1: Empty. 2-4: Water height * `anvil`: Anvil. 1: No damage. 2-3: Higher damage levels * `no_rename=1`: Item cannot be renamed by anvil diff --git a/mods/CORE/mcl_attached/init.lua b/mods/CORE/mcl_attached/init.lua index 4f538e104..c4a7a3337 100644 --- a/mods/CORE/mcl_attached/init.lua +++ b/mods/CORE/mcl_attached/init.lua @@ -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 facedir_to_dir = minetest.facedir_to_dir local get_item_group = minetest.get_item_group local remove_node = minetest.remove_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` node to drop. +-- * does not spread these updates to neighbours. +-- +-- Returns true if the node at has spawned a falling node or has been +-- dropped as item(s). +-- local original_function = minetest.check_single_for_falling function minetest.check_single_for_falling(pos) - local ret_o = original_function(pos) - local ret = false - local node = minetest.get_node(pos) + if original_function(pos) then + return true + end + + local node = get_node(pos) if get_item_group(node.name, "attached_node_facedir") ~= 0 then local dir = facedir_to_dir(node.param2) if dir then if get_item_group(get_node(vector.add(pos, dir)).name, "solid") == 0 then - remove_node(pos) - local drops = minetest.get_node_drops(node.name, "") - for dr=1, #drops do - minetest.add_item(pos, drops[dr]) - end - ret = true + drop_attached_node(pos) + return true end end end - return ret_o or ret + + 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 diff --git a/mods/ITEMS/mcl_wool/init.lua b/mods/ITEMS/mcl_wool/init.lua index c35ba9cf7..65cbb8708 100644 --- a/mods/ITEMS/mcl_wool/init.lua +++ b/mods/ITEMS/mcl_wool/init.lua @@ -75,7 +75,7 @@ for _, row in ipairs(wool.dyes) do tiles = {texture..".png"}, wield_image = texture..".png", wield_scale = { x=1, y=1, z=0.5 }, - groups = {handy=1, carpet=1,attached_node=1,flammable=1,fire_encouragement=60, fire_flammability=20, dig_by_water=1,deco_block=1,[color_group]=1}, + groups = {handy=1, carpet=1,supported_node=1,flammable=1,fire_encouragement=60, fire_flammability=20, dig_by_water=1,deco_block=1,[color_group]=1}, sounds = mcl_sounds.node_sound_wool_defaults(), paramtype = "light", sunlight_propagates = true,