nodecore-cd2025/mods/nc_api/item_falling_settle.lua
Aaron Suen 828f4a06d9 Try to fix faling node columns.
Before, settling was being processed out of order, so nodes could
fall into the space of nodes below and kick them out as items, so a
solid column of nodes could collapse and eject some nodes as items.
This makes hopper-feeding systems a pain to use.

Instead, explicitly signal upwards (tail-recursive) to settle all
falling nodes on the same tick, since they should already be falling
and accelerating downwards in lock-step.

This isn't perfect, as there are possible race conditions with things
being added into the node-space of the falling column while it's
falling, but it seems to work for now...
2019-10-15 20:35:26 -04:00

51 lines
1.5 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, setmetatable, vector
= minetest, nodecore, pairs, setmetatable, vector
-- LUALOCALS > ---------------------------------------------------------
local function signal(pos, ...)
pos = vector.round(pos)
pos.y = pos.y + 1
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 2)) do
if vector.equals(vector.round(obj:get_pos()), pos) then
obj = obj.get_luaentity and obj:get_luaentity()
if obj and obj.on_force_settle then
obj:on_force_settle(pos)
return signal(pos, ...)
end
end
end
return ...
end
local bifn = minetest.registered_entities["__builtin:falling_node"]
local falling = {
on_force_settle = function(self, pos)
local def = minetest.registered_nodes[self.node.name]
if def then
minetest.add_node(pos, self.node)
if self.meta then
minetest.get_meta(pos):from_table(self.meta)
end
nodecore.node_sound(pos, "place")
end
self.object:remove()
minetest.check_for_falling(pos)
end,
on_step = function(self, ...)
local oldnode = minetest.add_node
minetest.add_node = function(pos, node, ...)
minetest.add_node = oldnode
return signal(self.object:get_pos(),
oldnode(pos, node, ...))
end
local function helper(...)
minetest.add_node = oldnode
return ...
end
return helper(bifn.on_step(self, ...))
end
}
setmetatable(falling, bifn)
minetest.register_entity(":__builtin:falling_node", falling)