From 8d34ff9079808aa9f945ab8fb18ebc25f405afd6 Mon Sep 17 00:00:00 2001 From: The4codeblocks <72419529+The4codeblocks@users.noreply.github.com> Date: Wed, 7 May 2025 13:22:49 -0500 Subject: [PATCH] fix #15 and #62 (process split stacks) (#154) * fix #15 fixes #15 * fix luacheck stuff * I mean here * crash fix + allow arbitrary-count extraction * crash fix * wrong place * missed an end --- filter-injector.lua | 71 +++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/filter-injector.lua b/filter-injector.lua index 5345f33..2aee35e 100644 --- a/filter-injector.lua +++ b/filter-injector.lua @@ -117,8 +117,7 @@ local function punch_filter(data, filtpos, filtnode, msg) } -- make sure there's something appropriate to inject the item into - local todir = pipeworks.facedir_to_right_dir(filtnode.param2) - local topos = vector.add(filtpos, todir) + local topos = vector.add(filtpos, dir) local tonode = minetest.get_node(topos) local todef = minetest.registered_nodes[tonode.name] @@ -258,6 +257,7 @@ local function punch_filter(data, filtpos, filtnode, msg) if fromtube.before_filter then fromtube.before_filter(frompos) end local function grabAndFire(frominvname, filterfor) + if (exmatch_mode ~= 0) and not filterfor.count then return false end local sposes = {} if not frominvname or not frominv:get_list(frominvname) then return end for spos,stack in ipairs(frominv:get_list(frominvname)) do @@ -314,6 +314,7 @@ local function punch_filter(data, filtpos, filtnode, msg) return a < b end) end + local taken = 0 for _, spos in ipairs(sposes) do local stack = frominv:get_stack(frominvname, spos) local doRemove = stack:get_count() @@ -332,39 +333,53 @@ local function punch_filter(data, filtpos, filtnode, msg) filtmeta:set_int("slotseq_index", nextpos) set_filter_infotext(data, filtmeta) end - local item local count if data.stackwise then count = math.min(stack:get_count(), doRemove) - if filterfor.count and (filterfor.count > 1 or data.digiline) then - if exmatch_mode ~= 0 and filterfor.count > count then - return false -- not enough, fail - else - -- limit quantity to filter amount - count = math.min(filterfor.count, count) - end - end + taken = taken + count else - count = 1 + taken = 1 + break end - if fromtube.remove_items then - -- it could be the entire stack... - item = fromtube.remove_items(frompos, fromnode, stack, dir, count, frominvname, spos) - else - item = stack:take_item(count) - frominv:set_stack(frominvname, spos, stack) - if fromdef.on_metadata_inventory_take then - fromdef.on_metadata_inventory_take(frompos, frominvname, spos, item, fakeplayer) - end - end - local pos = vector.add(frompos, vector.multiply(dir, 1.4)) - local start_pos = vector.add(frompos, dir) - pipeworks.tube_inject_item(pos, start_pos, dir, item, - fakeplayer:get_player_name(), item_tags) - return true -- only fire one item, please end end - return false + local item + if taken == 0 then return false end + if (exmatch_mode ~= 0) and (filterfor.count > taken) then return false end + if filterfor.count then taken = math.min(taken, filterfor.count) end + local real_taken = 0 + if fromtube.remove_items then + for i, spos in ipairs(sposes) do + -- it could be the entire stack... + item = fromtube.remove_items(frompos, fromnode, frominv:get_stack(frominvname, spos), dir, taken, frominvname, spos) + local count = math.min(taken, item:get_count()) + taken = taken - count + real_taken = real_taken + count + if taken == 0 then break end + if not filterfor.count then break end + end + else + for i, spos in ipairs(sposes) do + -- it could be the entire stack... + local stack = frominv:get_stack(frominvname, spos) + local count = math.min(taken, stack:get_count()) + item = stack:take_item(taken) + frominv:set_stack(frominvname, spos, stack) + if fromdef.on_metadata_inventory_take then + fromdef.on_metadata_inventory_take(frompos, frominvname, spos, item, fakeplayer) + end + taken = taken - count + real_taken = real_taken + count + if taken == 0 then break end + if not filterfor.count then break end + end + end + local pos = vector.add(frompos, vector.multiply(dir, 1.4)) + local start_pos = vector.add(frompos, dir) + item:set_count(real_taken) + pipeworks.tube_inject_item(pos, start_pos, dir, item, + fakeplayer:get_player_name(), item_tags) + return true -- only fire one item, please end for _, frominvname in ipairs(type(fromtube.input_inventory) == "table" and fromtube.input_inventory or {fromtube.input_inventory}) do