Aaron Suen 2ce0a3b246 Fix wrong item display on drop-all items
If an item was settling too far away from where the item ent
landed, e.g. if pushed out by other settling items at the same
place, then it was using entity position to get visinv data
instead of node position.

Inform visinv ents of their actual node position instead of relying
on the object being reasonably close and rounding.  This fixes
multiple potential issues with visinv entity display and allows
these entities to be displaced arbitrarily far from their home
node and still function.
2021-07-06 07:25:03 -04:00

67 lines
2.0 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local ItemStack, math, minetest, nodecore, pairs, vector
= ItemStack, math, minetest, nodecore, pairs, vector
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
local stackonly = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_items) do
if v.groups and v.groups.is_stack_only then
stackonly[k] = true
end
end
end)
nodecore.register_item_entity_on_settle(function(self, pos)
local node = minetest.get_node(pos)
if node.name == "ignore" then return end
if pos.y - 1 >= nodecore.map_limit_min then
node = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z})
if node.name == "ignore" then return end
end
if self.nextscan and nodecore.gametime < self.nextscan then return end
self.nextscan = (self.nextscan or nodecore.gametime) + 0.75 + 0.5 * math_random()
local boxes = {}
local item = ItemStack(self.itemstring)
for rel in nodecore.settlescan() do
local p = vector.add(pos, rel)
local n = minetest.get_node(p)
if stackonly[n.name] then
item = nodecore.stack_add(p, item)
if item:is_empty() then
self.itemstring = ""
self.object:remove()
return true
end
else
boxes[#boxes + 1] = p
end
if nodecore.buildable_to(p) and (p.y >= nodecore.map_limit_min)
and (rel.y <= 0 or (p.y - 1 < nodecore.map_limit_min)
or nodecore.walkable({x = p.x, y = p.y - 1, z = p.z})) then
nodecore.place_stack(p, item)
minetest.get_meta(p):set_string("tweenfrom",
minetest.serialize(self.object:get_pos()))
self.on_step = function()
self.on_step = function() self.object:remove() end
end
nodecore.visinv_reuse_ents[minetest.hash_node_position(
vector.round(p))] = self
return true
end
end
for _, p in pairs(boxes) do
item = nodecore.stack_add(p, item)
if item:is_empty() then
self.itemstring = ""
self.object:remove()
return true
end
end
self.itemstring = item:to_string()
end)