Added advanced filter stuff.

This commit is contained in:
Andrew Lalis 2022-12-21 14:30:44 +01:00
parent 702c315428
commit dd97d16e05
1 changed files with 108 additions and 59 deletions

View File

@ -22,66 +22,114 @@ local function stackMatches(itemStack, name, fuzzy)
) )
end end
--[[ -- Creates a filter function that filters on items whose names match the given list of names.
The following describes an item filter: local function makeItemNamesFilter(names, fuzzy)
A table containing a filter mechanism. return function(item)
{ for _, itemName in pairs(names) do
filterFunction = stackMatches, if stackMatches(item, itemName, fuzzy) then
fuzzy = false, return true
whitelist = true
}
The filterFunction is defined like so:
function filterFunction(item, filter)
return true | false
end
]]--
function itemscript.makeFilter(var, fuzzy, whitelist)
local filter = {
filterFunction = nil,
fuzzy = fuzzy or false,
whitelist = whitelist
}
if type(var) == "string" then
-- If the filter is a single item name, define a single-item filter that matches against the name.
filter.filterFunction = function (item, filter)
local matches = stackMatches(item, var, filter.fuzzy)
if filter.whitelist then
return matches
else
return not matches
end end
end end
elseif type(var) == "table" then return false
-- If the filter is a list of item names, define a multi-item filter.
filter.filterFunction = function (item, filter)
for _, itemName in pairs(var) do
if filter.whitelist and stackMatches(item, itemName, filter.fuzzy) then
return true
elseif not filter.whitelist and not stackMatches(item, itemName, filter.fuzzy) then
return false
end
end
-- If whitelist and we couldn't find a match, return false.
-- If blacklist and we couldn't find a non-match, return true.
return not filter.whitelist
end
elseif type(var) == "function" then
-- Otherwise, just use the provided filter.
filter.filterFunction = var
end end
filter.apply = function(item) end
return filter.filterFunction(item, filter)
local function notFilter(filter)
return function(item)
return not filter(item)
end
end
local function andFilter(filters)
return function(item)
for _, filter in pairs(filters) do
if not filter(item) then
return false
end
end
return true
end
end
local function orFilter(filters)
return function(item)
for _, filter in pairs(filters) do
if filter(item) then
return true
end
end
return false
end
end
-- Parses a filter expression string and returns a filter that implements it.
--[[
Item Filter Expressions:
A filter expression is a way to define a complex method of matching item
stacks.
Prepending ! will match any item stack whose name does not match.
Prepending # will do a fuzzy match using string.find.
]]--
local function parseItemFilterExpression(expr)
local prefixIdx, prefixIdxEnd = string.find(expr, "^[!#]*")
local fuzzy = false
local negated = false
if prefixIdx ~= nil then
for i = prefixIdx, i <= prefixIdxEnd do
if expr[i] == "!" then
negated = true
elseif expr[i] == "#" then
fuzzy = true
end
end
expr = string.sub(expr, prefixIdxEnd + 1, string.len(expr))
end
local namespaceSeparatorIdx = string.find(expr, ":")
if namespaceSeparatorIdx == nil and not fuzzy then
expr = "minecraft:" .. expr
end
local filter = makeItemNamesFilter({expr}, fuzzy)
if negated then
filter = notFilter(filter)
end end
return filter return filter
end end
-- Gets the total number of items of a certain type in the turtle's inventory. -- Converts an arbitrary variable into a filter; useful for any function that's public, so users can supply any filter.
function itemscript.totalCount(filter) -- It converts the following:
-- filter function tables directly.
-- strings and lists of strings are translated into an item names filter.
-- Functions are added with default fuzzy and whitelist parameters.
local function convertToFilter(var)
if type(var) == "table" and #var > 0 and type(var[1]) == "string" then
local filters = {}
for _, expr in pairs(var) do
table.insert(filters, parseFilterExpression(expr))
end
return orFilter(filters)
elseif type(var) == "string" then
return parseFilterExpression(var)
elseif type(var) == "function" then
return var
else
error("Unsupported filter type: " .. type(var))
end
end
-- Convenience function for creating a filter function that allows specifying fuzziness.
function itemscript.nameFilter(name, fuzzy)
return makeItemNamesFilter({name}, fuzzy)
end
-- Gets the total number of items in the turtle's inventory that match the given expression.
function itemscript.totalCount(filterExpr)
local filter = convertToFilter(filterExpr)
local count = 0 local count = 0
for i = 1, 16 do for i = 1, 16 do
local item = t.getItemDetail(i) local item = t.getItemDetail(i)
if filter.apply(item) then if filter(item) then
count = count + item.count count = count + item.count
end end
end end
@ -90,10 +138,11 @@ end
-- Selects a slot containing at least one of the given item type. -- Selects a slot containing at least one of the given item type.
-- Returns a boolean indicating whether we could find and select the item. -- Returns a boolean indicating whether we could find and select the item.
function itemscript.select(filter) function itemscript.select(filterExpr)
local filter = convertToFilter(filterExpr)
for i = 1, 16 do for i = 1, 16 do
local item = t.getItemDetail(i) local item = t.getItemDetail(i)
if filter.apply(item) then if filter(item) then
t.select(i) t.select(i)
return true return true
end end
@ -105,23 +154,23 @@ end
local function dropFiltered(dropFunction, filter) local function dropFiltered(dropFunction, filter)
for i = 1, 16 do for i = 1, 16 do
local item = t.getItemDetail(i) local item = t.getItemDetail(i)
if filter.apply(item) then if filter(item) then
t.select(i) t.select(i)
dropFunction() dropFunction()
end end
end end
end end
function itemscript.dropAll(filter) function itemscript.dropAll(filterExpr)
dropFiltered(t.drop, filter) dropFiltered(t.drop, convertToFilter(filterExpr))
end end
function itemscript.dropAllDown(filter) function itemscript.dropAllDown(filterExpr)
dropFiltered(t.dropDown, filter) dropFiltered(t.dropDown, convertToFilter(filterExpr))
end end
function itemscript.dropAllUp(filter) function itemscript.dropAllUp(filterExpr)
dropFiltered(t.dropUp, filter) dropFiltered(t.dropUp, convertToFilter(filterExpr))
end end
-- Cleans up the turtle's inventory by compacting all stacks of items. -- Cleans up the turtle's inventory by compacting all stacks of items.