mirror of
https://github.com/mt-mods/pipeworks.git
synced 2024-11-09 17:03:58 +01:00
Merge branch 'filter-injector-refactor' into 'master'
filter-injector.lua: eliminate most parameters from grabAndFire by making it a closure See merge request VanessaE/pipeworks!13
This commit is contained in:
commit
0fa88b7054
@ -53,116 +53,6 @@ local function set_filter_formspec(data, meta)
|
|||||||
meta:set_string("formspec", formspec)
|
meta:set_string("formspec", formspec)
|
||||||
end
|
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 function punch_filter(data, filtpos, filtnode, msg)
|
||||||
local filtmeta = minetest.get_meta(filtpos)
|
local filtmeta = minetest.get_meta(filtpos)
|
||||||
local filtinv = filtmeta:get_inventory()
|
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
|
if not (fromtube and fromtube.input_inventory) then return end
|
||||||
|
|
||||||
local slotseq_mode
|
local slotseq_mode
|
||||||
local exact_match
|
local exmatch_mode
|
||||||
|
|
||||||
local filters = {}
|
local filters = {}
|
||||||
if data.digiline then
|
if data.digiline then
|
||||||
@ -251,10 +141,10 @@ local function punch_filter(data, filtpos, filtnode, msg)
|
|||||||
|
|
||||||
local exmatch = msg.exmatch
|
local exmatch = msg.exmatch
|
||||||
local t_exmatch = type(exmatch)
|
local t_exmatch = type(exmatch)
|
||||||
if t_exmatch == "number" and exmatch >= 0 and exmatch <= 1 then
|
if t_exmatch == "number" and (exmatch == 0 or exmatch == 1) then
|
||||||
exact_match = exmatch
|
exmatch_mode = exmatch
|
||||||
elseif t_exmatch == "boolean" then
|
elseif t_exmatch == "boolean" then
|
||||||
exact_match = exmatch and 1 or 0
|
exmatch_mode = exmatch and 1 or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local slotseq_index = msg.slotseq_index
|
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)
|
filtmeta:set_int("slotseq_mode", slotseq_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
if exact_match ~= nil then
|
if exmatch_mode ~= nil then
|
||||||
filtmeta:set_int("exmatch_mode", exact_match)
|
filtmeta:set_int("exmatch_mode", exmatch_mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
if slotseq_mode ~= nil or exact_match ~= nil then
|
if slotseq_mode ~= nil or exmatch_mode ~= nil then
|
||||||
set_filter_formspec(data, filtmeta)
|
set_filter_formspec(data, filtmeta)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -313,8 +203,8 @@ local function punch_filter(data, filtpos, filtnode, msg)
|
|||||||
slotseq_mode = filtmeta:get_int("slotseq_mode")
|
slotseq_mode = filtmeta:get_int("slotseq_mode")
|
||||||
end
|
end
|
||||||
|
|
||||||
if exact_match == nil then
|
if exmatch_mode == nil then
|
||||||
exact_match = filtmeta:get_int("exmatch_mode")
|
exmatch_mode = filtmeta:get_int("exmatch_mode")
|
||||||
end
|
end
|
||||||
|
|
||||||
local frominv
|
local frominv
|
||||||
@ -328,10 +218,120 @@ local function punch_filter(data, filtpos, filtnode, msg)
|
|||||||
frominv = frommeta:get_inventory()
|
frominv = frommeta:get_inventory()
|
||||||
end
|
end
|
||||||
if fromtube.before_filter then fromtube.before_filter(frompos) 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
|
for _, frominvname in ipairs(type(fromtube.input_inventory) == "table" and fromtube.input_inventory or {fromtube.input_inventory}) do
|
||||||
local done = false
|
local done = false
|
||||||
for _, filterfor in ipairs(filters) do
|
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
|
done = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user