From 8f03c0e6849efd048c2640249724cb405bd86c28 Mon Sep 17 00:00:00 2001 From: electrodude Date: Fri, 10 Jan 2020 19:48:57 +0000 Subject: [PATCH] filter-injector.lua: Rename exact_match -> exmatch_mode Also fixed bad conditional that would accept non-integer values of exmatch in a message. --- filter-injector.lua | 240 ++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/filter-injector.lua b/filter-injector.lua index 675ea07..316e76a 100644 --- a/filter-injector.lua +++ b/filter-injector.lua @@ -53,116 +53,6 @@ local function set_filter_formspec(data, meta) meta:set_string("formspec", formspec) end --- todo SOON: this function has *way too many* parameters -local function grabAndFire(data,slotseq_mode,exmatch_mode,filtmeta,frominv,frominvname,frompos,fromnode,filterfor,fromtube,fromdef,dir,fakePlayer,all,digiline) - local sposes = {} - if not frominvname or not frominv:get_list(frominvname) then return end - for spos,stack in ipairs(frominv:get_list(frominvname)) do - local matches - if filterfor == "" then - matches = stack:get_name() ~= "" - else - local fname = filterfor.name - local fgroup = filterfor.group - local fwear = filterfor.wear - local fmetadata = filterfor.metadata - matches = (not fname -- If there's a name filter, - or stack:get_name() == fname) -- it must match. - - and (not fgroup -- If there's a group filter, - or (type(fgroup) == "string" -- it must be a string - and minetest.get_item_group( -- and it must match. - stack:get_name(), fgroup) ~= 0)) - - and (not fwear -- If there's a wear filter: - or (type(fwear) == "number" -- If it's a number, - and stack:get_wear() == fwear) -- it must match. - or (type(fwear) == "table" -- If it's a table: - and (not fwear[1] -- If there's a lower bound, - or (type(fwear[1]) == "number" -- it must be a number - and fwear[1] <= stack:get_wear())) -- and it must be <= the actual wear. - and (not fwear[2] -- If there's an upper bound - or (type(fwear[2]) == "number" -- it must be a number - and stack:get_wear() < fwear[2])))) -- and it must be > the actual wear. - -- If the wear filter is of any other type, fail. - -- - and (not fmetadata -- If there's a matadata filter, - or (type(fmetadata) == "string" -- it must be a string - and stack:get_metadata() == fmetadata)) -- and it must match. - end - if matches then table.insert(sposes, spos) end - end - if #sposes == 0 then return false end - if slotseq_mode == 1 then - for i = #sposes, 2, -1 do - local j = math.random(i) - local t = sposes[j] - sposes[j] = sposes[i] - sposes[i] = t - end - elseif slotseq_mode == 2 then - local headpos = filtmeta:get_int("slotseq_index") - table.sort(sposes, function (a, b) - if a >= headpos then - if b < headpos then return true end - else - if b >= headpos then return false end - end - return a < b - end) - end - for _, spos in ipairs(sposes) do - local stack = frominv:get_stack(frominvname, spos) - local doRemove = stack:get_count() - if fromtube.can_remove then - doRemove = fromtube.can_remove(frompos, fromnode, stack, dir, frominvname, spos) - elseif fromdef.allow_metadata_inventory_take then - doRemove = fromdef.allow_metadata_inventory_take(frompos, frominvname,spos, stack, fakePlayer) - end - -- stupid lack of continue statements grumble - if doRemove > 0 then - if slotseq_mode == 2 then - local nextpos = spos + 1 - if nextpos > frominv:get_size(frominvname) then - nextpos = 1 - end - filtmeta:set_int("slotseq_index", nextpos) - set_filter_infotext(data, filtmeta) - end - local item - local count - if all then - count = math.min(stack:get_count(), doRemove) - if filterfor.count and (filterfor.count > 1 or 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 - else - count = 1 - 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) - local item1 = pipeworks.tube_inject_item(pos, start_pos, dir, item, fakePlayer:get_player_name()) - return true-- only fire one item, please - end - end - return false -end - local function punch_filter(data, filtpos, filtnode, msg) local filtmeta = minetest.get_meta(filtpos) local filtinv = filtmeta:get_inventory() @@ -214,7 +104,7 @@ local function punch_filter(data, filtpos, filtnode, msg) if not (fromtube and fromtube.input_inventory) then return end local slotseq_mode - local exact_match + local exmatch_mode local filters = {} if data.digiline then @@ -251,10 +141,10 @@ local function punch_filter(data, filtpos, filtnode, msg) local exmatch = msg.exmatch local t_exmatch = type(exmatch) - if t_exmatch == "number" and exmatch >= 0 and exmatch <= 1 then - exact_match = exmatch + if t_exmatch == "number" and (exmatch == 0 or exmatch == 1) then + exmatch_mode = exmatch elseif t_exmatch == "boolean" then - exact_match = exmatch and 1 or 0 + exmatch_mode = exmatch and 1 or 0 end local slotseq_index = msg.slotseq_index @@ -271,11 +161,11 @@ local function punch_filter(data, filtpos, filtnode, msg) filtmeta:set_int("slotseq_mode", slotseq_mode) end - if exact_match ~= nil then - filtmeta:set_int("exmatch_mode", exact_match) + if exmatch_mode ~= nil then + filtmeta:set_int("exmatch_mode", exmatch_mode) end - if slotseq_mode ~= nil or exact_match ~= nil then + if slotseq_mode ~= nil or exmatch_mode ~= nil then set_filter_formspec(data, filtmeta) end @@ -313,8 +203,8 @@ local function punch_filter(data, filtpos, filtnode, msg) slotseq_mode = filtmeta:get_int("slotseq_mode") end - if exact_match == nil then - exact_match = filtmeta:get_int("exmatch_mode") + if exmatch_mode == nil then + exmatch_mode = filtmeta:get_int("exmatch_mode") end local frominv @@ -328,10 +218,120 @@ local function punch_filter(data, filtpos, filtnode, msg) frominv = frommeta:get_inventory() end if fromtube.before_filter then fromtube.before_filter(frompos) end + + local function grabAndFire(frominvname, filterfor) + local sposes = {} + if not frominvname or not frominv:get_list(frominvname) then return end + for spos,stack in ipairs(frominv:get_list(frominvname)) do + local matches + if filterfor == "" then + matches = stack:get_name() ~= "" + else + local fname = filterfor.name + local fgroup = filterfor.group + local fwear = filterfor.wear + local fmetadata = filterfor.metadata + matches = (not fname -- If there's a name filter, + or stack:get_name() == fname) -- it must match. + + and (not fgroup -- If there's a group filter, + or (type(fgroup) == "string" -- it must be a string + and minetest.get_item_group( -- and it must match. + stack:get_name(), fgroup) ~= 0)) + + and (not fwear -- If there's a wear filter: + or (type(fwear) == "number" -- If it's a number, + and stack:get_wear() == fwear) -- it must match. + or (type(fwear) == "table" -- If it's a table: + and (not fwear[1] -- If there's a lower bound, + or (type(fwear[1]) == "number" -- it must be a number + and fwear[1] <= stack:get_wear())) -- and it must be <= the actual wear. + and (not fwear[2] -- If there's an upper bound + or (type(fwear[2]) == "number" -- it must be a number + and stack:get_wear() < fwear[2])))) -- and it must be > the actual wear. + -- If the wear filter is of any other type, fail. + + and (not fmetadata -- If there's a metadata filter, + or (type(fmetadata) == "string" -- it must be a string + and stack:get_metadata() == fmetadata)) -- and it must match. + end + if matches then table.insert(sposes, spos) end + end + if #sposes == 0 then return false end + if slotseq_mode == 1 then + for i = #sposes, 2, -1 do + local j = math.random(i) + local t = sposes[j] + sposes[j] = sposes[i] + sposes[i] = t + end + elseif slotseq_mode == 2 then + local headpos = filtmeta:get_int("slotseq_index") + table.sort(sposes, function (a, b) + if a >= headpos then + if b < headpos then return true end + else + if b >= headpos then return false end + end + return a < b + end) + end + for _, spos in ipairs(sposes) do + local stack = frominv:get_stack(frominvname, spos) + local doRemove = stack:get_count() + if fromtube.can_remove then + doRemove = fromtube.can_remove(frompos, fromnode, stack, dir, frominvname, spos) + elseif fromdef.allow_metadata_inventory_take then + doRemove = fromdef.allow_metadata_inventory_take(frompos, frominvname,spos, stack, fakePlayer) + end + -- stupid lack of continue statements grumble + if doRemove > 0 then + if slotseq_mode == 2 then + local nextpos = spos + 1 + if nextpos > frominv:get_size(frominvname) then + nextpos = 1 + end + 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 + else + count = 1 + 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) + local item1 = pipeworks.tube_inject_item(pos, start_pos, dir, item, fakePlayer:get_player_name()) + return true -- only fire one item, please + end + end + return false + end + for _, frominvname in ipairs(type(fromtube.input_inventory) == "table" and fromtube.input_inventory or {fromtube.input_inventory}) do local done = false for _, filterfor in ipairs(filters) do - if grabAndFire(data, slotseq_mode, exact_match, filtmeta, frominv, frominvname, frompos, fromnode, filterfor, fromtube, fromdef, dir, fakePlayer, data.stackwise, data.digiline) then + if grabAndFire(frominvname, filterfor) then done = true break end