Add listItemsRaw(), listProviders() and defrag() to storage.lua
listItemsRaw provides a raw list of the items in all storage chests listProviders provides a list of items and which chests contain them defrag defragments the storage system
This commit is contained in:
@@ -291,6 +291,89 @@ function Storage:listItems(throttle)
|
||||
return self.cache
|
||||
end
|
||||
|
||||
-- provide a raw list of all the items in all storage chests
|
||||
-- it might be beneficial to move this to the adapter class at some point and cache the raw item list in this class at some point
|
||||
function Storage:listItemsRaw()
|
||||
local res = {}
|
||||
|
||||
for _, v in pairs(self.nodes) do
|
||||
if v.category == "storage" then
|
||||
local chest = device[v.name]
|
||||
local items = chest.list()
|
||||
|
||||
for slot, item in pairs(items) do
|
||||
items[slot] = itemDB:get(item, function() return chest.getItemMeta(slot) end)
|
||||
end
|
||||
|
||||
res[v.name] = items
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
-- provide a list of items and which chests provide them
|
||||
function Storage:listProviders()
|
||||
local res = {}
|
||||
|
||||
local rawItems = self:listItemsRaw()
|
||||
|
||||
for chest, items in pairs(rawItems) do
|
||||
for slot, item in pairs(items) do
|
||||
local key = table.concat({item.name, item.damage, item.nbtHash}, ":")
|
||||
if not res[key] then
|
||||
res[key] = {}
|
||||
end
|
||||
table.insert(res[key], {item = item, device = device[chest], slot = slot})
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- defrags the storage system
|
||||
function Storage:defrag()
|
||||
local items = self:listProviders()
|
||||
|
||||
for _, providers in pairs(items) do
|
||||
table.sort(providers, function(a, b)
|
||||
return a.item.count < b.item.count
|
||||
end)
|
||||
|
||||
-- We're done when we either compressed the stacks so far, that there's only one left (#providers == 1)
|
||||
-- Or when we've compressed so far, that the there's only one stack which has a lower count than the maxCount
|
||||
-- Because of the sorting, we know that this will be the stack in providers[1], so we check if providers[2] is at the maxCount
|
||||
while #providers > 1 and providers[2].item.count ~= providers[2].item.maxCount do
|
||||
local from = providers[1]
|
||||
local to
|
||||
|
||||
-- We're pushing to the highest stack which is still below the maxCount, this way as many slots as possible will be filled
|
||||
-- This loop is guarenteed to assign a value to "to", as the only cases where it wouldn't (#providers == 1 or no provider with less than maxCount)
|
||||
-- are ruled out by the condition of the outer while loop
|
||||
for i = 2, #providers do
|
||||
if providers[i].item.count < providers[i].item.maxCount then
|
||||
to = providers[i]
|
||||
else
|
||||
-- As this slot is already at maxCount, all the remaining ones will also be due to sorting
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local toMove = math.min(to.item.maxCount - to.item.count, from.item.count)
|
||||
from.device.pushItems(to.device.name, from.slot, toMove, to.slot)
|
||||
to.item.count = to.item.count + toMove
|
||||
from.item.count = from.item.count - toMove
|
||||
|
||||
if from.item.count <= 0 then
|
||||
table.remove(providers, 1)
|
||||
end
|
||||
|
||||
table.sort(providers, function(a, b)
|
||||
return a.item.count < b.item.count
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Storage:updateCache(adapter, item, count)
|
||||
if not adapter.cache then
|
||||
adapter.dirty = true
|
||||
|
||||
Reference in New Issue
Block a user