Add a Defragment button to Milo #36

Merged
Luca0208 merged 10 commits from develop-1.8-milo-defrag into develop-1.8 2020-05-10 01:48:40 -04:00
Showing only changes of commit 95010cfc07 - Show all commits

View File

@@ -291,6 +291,89 @@ function Storage:listItems(throttle)
return self.cache
kepler155c commented 2020-05-01 00:42:04 -04:00 (Migrated from github.com)
Review

There might be cases where pushItems will generate an error (ie. if the user's ender chest is set to storage for some reason and they are offline). It would be best to wrap the pushItems in a pcall().

There might be cases where pushItems will generate an error (ie. if the user's ender chest is set to storage for some reason and they are offline). It would be best to wrap the pushItems in a pcall().
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()
kepler155c commented 2020-05-01 00:37:32 -04:00 (Migrated from github.com)
Review

Need to check if a chest is locked to specific items. There's 2 different ways to go here:

  1. the easy way - ignore locked chests.
  2. process the locked chests first - only pulling items in that match the filter.

My vote is for #2 :)

Need to check if a chest is locked to specific items. There's 2 different ways to go here: 1. the easy way - ignore locked chests. 2. process the locked chests first - only pulling items in that match the filter. My vote is for #2 :)
Luca0208 commented 2020-05-04 16:29:23 -04:00 (Migrated from github.com)
Review

Just so I get this right, when a chest is locked it would be enough to prioritise that chest when trying to find a target for the item?

Just so I get this right, when a chest is locked it would be enough to prioritise that chest when trying to find a target for the item?
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