Newer
Older
Radon / core / inventory / ScanInventory.lua
@Allymonies Allymonies on 24 Dec 2022 4 KB Inventory & Stock levels
local itemCache = {}

local function getInventories()
    peripherals = peripheral.getNames()
    inventories = {}
    for i = 1, #peripherals do
        name = peripherals[i]
        local methods = peripheral.getMethods(name)
        local hasListItems = false
        local hasPushItems = false
        if methods then
            for i = 1, #methods do
                if methods[i] == "list" then
                    hasListItems = true
                end
                if methods[i] == "pushItems" then
                    hasPushItems = true
                end
                if hasListItems and hasPushItems then
                    break
                end
            end
        end
        if hasListItems and hasPushItems then
            table.insert(inventories, peripheral.wrap(name))
        end
    end
    return inventories
end

local function getInventoryItems(inventory)
    local inventoryName = peripheral.getName(inventory)
    local items = {}
    local slots = inventory.list()
    for slot, item in pairs(slots) do
        if item then
            item.inventory = inventoryName
            item.slot = slot
            table.insert(items, item)
        end
    end
    return items
end

local function getAllInventoryItems(inventories)
    local items = {}
    for i = 1, #inventories do
        local inventory = inventories[i]
        local inventoryItems = getInventoryItems(inventory)
        for i = 1, #inventoryItems do
            table.insert(items, inventoryItems[i])
        end
    end
    return items
end

local partialObjectMatches
local function partialArrayMatches(partialArray, array)
    for i = 1, #partialArray do
        local found = false
        for i = 1, #array do
            if type(array[i]) == "table" then
                if partialObjectMatches(partialArray[i], array[i]) then
                    found = true
                    break
                end
            elseif partialArray[i] == array[i] then
                found = true
                break
            end
        end
        if not found then
            return false
        end
    end
    return true
end

function partialObjectMatches(partialObject, object)
    if type(object) ~= "table" then
        return false
    end
    if object[1] then
        return partialArrayMatches(partialObject, object)
    end
    for k,v in pairs(partialObject) do
        if type(v) == "table" then
            if not partialObjectMatches(v, object[k]) then
                return false
            end
        elseif object[k] == nil or object[k] ~= v then
            return false
        end
    end
    return true
end

local function predicateMatches(predicates, item)
    local meta = peripheral.call(item.inventory, "getItemMeta", item.slot)
    return partialObjectMatches(predicates, meta)
end

local function findMatchingProducts(products, item)
    local matchingProducts = {}
    for i = 1, #products do
        local product = products[i]
        if item.name == product.modid then
            if not product.predicates or predicateMatches(product.predicates, item) then
                table.insert(matchingProducts, product)
            end
        end
    end
    return matchingProducts
end

local function updateProductInventory(products)
    for i = 1, #products do
        products[i].newQty = 0
    end
    local inventories = getInventories()
    local items = getAllInventoryItems(inventories)
    itemCache = items
    for i = 1, #items do
        local item = items[i]
        local matchingProducts = findMatchingProducts(products, item)
        for i = 1, #matchingProducts do
            local product = matchingProducts[i]
            product.newQty = product.newQty + item.count
        end
    end
    for i = 1, #products do
        local product = products[i]
        product.quantity = product.newQty
        product.newQty = nil
    end
end

local function getItemCache()
    return itemCache
end

return {
    updateProductInventory = updateProductInventory,
    getItemCache = getItemCache
}