summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter-injector.lua240
1 files 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