From ce994122700644ca9df4f5426b3ca23f3f31070b Mon Sep 17 00:00:00 2001 From: Aaron Suen Date: Sat, 27 Nov 2021 15:08:40 -0500 Subject: [PATCH] Item entities properly fall thru forms --- mods/nc_api/init.lua | 2 ++ mods/nc_api/util_stack.lua | 15 ++++++++++++--- mods/nc_api_storebox/init.lua | 10 ++++++++++ mods/nc_items/ent_item.lua | 34 +++++++++++++++++----------------- mods/nc_woodwork/shelf.lua | 22 +++++++++++++++++----- 5 files changed, 58 insertions(+), 25 deletions(-) diff --git a/mods/nc_api/init.lua b/mods/nc_api/init.lua index 3352fda3..21e82a93 100644 --- a/mods/nc_api/init.lua +++ b/mods/nc_api/init.lua @@ -81,6 +81,8 @@ do minetest.after(0, regreport) end +nodecore.add_item_raw = minetest.add_item + include("compat_clientversion") include("compat_creative") include("compat_issue10127") diff --git a/mods/nc_api/util_stack.lua b/mods/nc_api/util_stack.lua index 70412564..53f8d3c1 100644 --- a/mods/nc_api/util_stack.lua +++ b/mods/nc_api/util_stack.lua @@ -142,13 +142,22 @@ function nodecore.stack_giveto(pos, player, node, def) return stack:is_empty() end -function nodecore.stack_settle(pos, stack, node, def) +function nodecore.stack_settle(pos, stack, node, def, inside) stack = ItemStack(stack) if stack:is_empty() then return stack end node = node or minetest.get_node(pos) def = def or minetest.registered_items[node.name] or {} if not def.on_settle_item then return stack end - return def.on_settle_item(pos, node, stack) + return def.on_settle_item(pos, node, stack, inside) +end + +function nodecore.stack_can_fall_in(pos, stack, node, def, ent) + stack = ItemStack(stack) + if stack:is_empty() then return end + node = node or minetest.get_node(pos) + def = def or minetest.registered_items[node.name] or {} + if not def.can_item_fall_in then return def.buildable_to end + return def.can_item_fall_in(pos, node, stack, ent) end local ejectdir @@ -214,7 +223,7 @@ function nodecore.item_eject(pos, stack, speed, qty, vel) } end local p = {x = pos.x, y = pos.y + 0.25, z = pos.z} - local obj = minetest.add_item(p, stack) + local obj = nodecore.add_item_raw(p, stack) if obj then obj:set_velocity(v) end end end diff --git a/mods/nc_api_storebox/init.lua b/mods/nc_api_storebox/init.lua index 76cf1ef4..668f0ad6 100644 --- a/mods/nc_api_storebox/init.lua +++ b/mods/nc_api_storebox/init.lua @@ -69,6 +69,15 @@ function nodecore.storebox_on_settle_item(pos, node, stack) return nodecore.stack_add(pos, stack) end +function nodecore.storebox_can_item_fall_in(pos, node) + if not nodecore.stack_get(pos):is_empty() then return end + local def = node and minetest.registered_items[node.name] or {} + if def.storebox_access and (not def.storebox_access( + {type = "node", above = {x = pos.x, y = pos.y + 1, z = pos.z}, + under = pos}, pos, node)) then return end + return true +end + nodecore.register_on_register_item(function(_, def) if def.type ~= "node" or (not def.groups) or (not def.groups.storebox) then return end @@ -91,4 +100,5 @@ nodecore.register_on_register_item(function(_, def) def.on_punch = def.on_punch or nodecore.storebox_on_punch def.stack_allow = def.stack_allow or nodecore.storebox_stack_allow def.on_settle_item = def.on_settle_item or nodecore.storebox_on_settle_item + def.can_item_fall_in = def.can_item_fall_in or nodecore.storebox_can_item_fall_in end) diff --git a/mods/nc_items/ent_item.lua b/mods/nc_items/ent_item.lua index 44b28a07..1042ffb2 100644 --- a/mods/nc_items/ent_item.lua +++ b/mods/nc_items/ent_item.lua @@ -14,6 +14,12 @@ minetest.after(0, function() end end) +local function nuke(self) + self.itemstring = "" + self.object:remove() + return true +end + nodecore.register_item_entity_on_settle(function(self, pos) local curnode = minetest.get_node(pos) if curnode.name == "ignore" then return end @@ -25,12 +31,15 @@ nodecore.register_item_entity_on_settle(function(self, pos) then return end local item = ItemStack(self.itemstring) - item = nodecore.stack_settle(pos, item, bnode) - if item:is_empty() then - self.itemstring = "" - self.object:remove() - return true + item = nodecore.stack_settle(pos, item, curnode, nil, true) + if item:is_empty() then return nuke(self) end + if nodecore.stack_can_fall_in(below, item, bnode, nil, self) then + self.object:set_pos({x = pos.x, y = pos.y - 0.55, z = pos.z}) + self.object:set_velocity({x = 0, y = 0, z = 0}) + return end + item = nodecore.stack_settle(below, item, bnode) + if item:is_empty() then return nuke(self) 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() @@ -41,11 +50,7 @@ nodecore.register_item_entity_on_settle(function(self, pos) 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 + if item:is_empty() then return nuke(self) end else boxes[#boxes + 1] = p end @@ -55,17 +60,12 @@ nodecore.register_item_entity_on_settle(function(self, pos) nodecore.place_stack(p, item) minetest.get_meta(p):set_string("tweenfrom", minetest.serialize(self.object:get_pos())) - self.object:remove() - return true + return nuke(self) 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 + if item:is_empty() then return nuke(self) end end self.itemstring = item:to_string() end) diff --git a/mods/nc_woodwork/shelf.lua b/mods/nc_woodwork/shelf.lua index b1a0aff3..293f6e95 100644 --- a/mods/nc_woodwork/shelf.lua +++ b/mods/nc_woodwork/shelf.lua @@ -29,12 +29,24 @@ minetest.register_node(modname .. ":form", { return nodecore.stack_get(pos) end end, + on_settle_item = function(pos, node, stack, inside, ...) + if inside and nodecore.stack_can_fall_in({ + x = pos.x, + y = pos.y - 1, + z = pos.z + }, stack) then return stack end + return nodecore.storebox_on_settle_item(pos, node, stack, inside, ...) + end, on_stack_change = function(pos, _, stack) - nodecore.stack_set(pos, nodecore.stack_settle({ - x = pos.x, - y = pos.y - 1, - z = pos.z - }, stack)) + if stack:is_empty() then return end + print(stack:to_string()) + if not nodecore.stack_can_fall_in({ + x = pos.x, + y = pos.y - 1, + z = pos.z + }, stack) then return end + nodecore.stack_set(pos, "") + nodecore.item_eject(pos, stack) end })