From 7c766d959779d377a6d24f1b5d25f6bcd77c6697 Mon Sep 17 00:00:00 2001 From: Sokomine Date: Fri, 19 Jan 2024 19:43:47 +0100 Subject: [PATCH] added soft_falling.lua - which is a slight modification of builtin/game/falling.lua but more suitable for snow --- init.lua | 1 + soft_falling.lua | 106 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 soft_falling.lua diff --git a/init.lua b/init.lua index 55953d0..b3ab7fd 100644 --- a/init.lua +++ b/init.lua @@ -89,6 +89,7 @@ dofile(modpath..'crafts.lua') -- make sure default:snow does not crush plants minetest.registered_nodes["default:snow"].groups.soft_falling = 1 +dofile(modpath..'soft_falling.lua') --[[ -- remove the "attached_node" value from farming plants; diff --git a/soft_falling.lua b/soft_falling.lua new file mode 100644 index 0000000..a5c61a2 --- /dev/null +++ b/soft_falling.lua @@ -0,0 +1,106 @@ + +-- moresnow shall not crush plants (buildable_to is set) when falling +-- on them - snow is not like sand or gravel (at least when falling slowly) +local old_try_place = minetest.registered_entities["__builtin:falling_node"].try_place +minetest.registered_entities["__builtin:falling_node"].try_place = function(self, bcp, bcn) + if core.get_item_group(self.node.name, "soft_falling") == 0 then + return old_try_place(self, bcp, bcn) + end + return moresnow.new_try_place(self, bcp, bcn) +end + + +-- avoid cascades of dropping moresnow nodes that are actually sitting +-- perfectly well on buildable_to plants +local old_check_single_for_falling = core.check_single_for_falling +core.check_single_for_falling = function(p) + return moresnow.check_single_for_falling(p) +end + + +-- this is a only minimally modified copy of the function in builtin/game/falling.lua: +moresnow.new_try_place = function(self, bcp, bcn) + local bcd = core.registered_nodes[bcn.name] + -- Add levels if dropped on same leveled node + if bcd and bcd.paramtype2 == "leveled" and + bcn.name == self.node.name then + local addlevel = self.node.level + if (addlevel or 0) <= 0 then + addlevel = bcd.leveled + end + if core.add_node_level(bcp, addlevel) < addlevel then + return true + elseif bcd.buildable_to then + -- Node level has already reached max, don't place anything + return true + end + end + + -- Decide if we're replacing the node or placing on top + local np = vector.copy(bcp) + if bcd and bcd.buildable_to and + (not self.floats or bcd.liquidtype == "none") then + core.remove_node(bcp) + else + np.y = np.y + 1 + end + + -- Check what's here + local n2 = core.get_node(np) + local nd = core.registered_nodes[n2.name] + -- If it's not air or liquid, remove node and replace it with + -- it's drops + if n2.name ~= "air" and (not nd or nd.liquidtype == "none") then + if nd and nd.buildable_to == false then + nd.on_dig(np, n2, nil) + -- If it's still there, it might be protected + if core.get_node(np).name == n2.name then + return false + end + else + if core.get_item_group(self.node.name, "soft_falling") == 0 then + core.remove_node(np) + else + -- do not crush the plant below! + np.y = np.y + 1 + end + end + end + + -- Create node + local def = core.registered_nodes[self.node.name] + if def then + core.add_node(np, self.node) + if self.meta then + core.get_meta(np):from_table(self.meta) + end + if def.sounds and def.sounds.place then + core.sound_play(def.sounds.place, {pos = np}, true) + end + end + core.check_for_falling(np) + return true +end + + +-- this is a only minimally modified copy of the function in builtin/game/falling.lua: +moresnow.check_single_for_falling = function(p) + local n = core.get_node(p) + if core.get_item_group(n.name, "falling_node") ~= 0 then + local p_bottom = vector.offset(p, 0, -1, 0) + -- Only spawn falling node if node below is loaded + local n_bottom = core.get_node_or_nil(p_bottom) + local d_bottom = n_bottom and core.registered_nodes[n_bottom.name] + if d_bottom then + -- do not trigger a cascade of falling nodes when it's just + -- moresnow nodes that rest perfectly well on top of plants (buildable_to) + if(d_bottom.name and d_bottom.name ~= "air" + and core.get_item_group(n.name, "soft_falling") > 0) then + return false + end + end + end + -- makes use of local builtin_shared variable which we don't have available here - so + -- we need to call the original + return old_check_single_for_falling(p) +end