feat: implement parallel inventory scanning and supply chest functionality

This commit is contained in:
MayaTheShy
2026-03-22 18:15:50 -04:00
parent 314fec5c47
commit 76772140aa

View File

@@ -148,13 +148,39 @@ function O.refreshCache(onProgress)
local totalSlots = 0
local usedSlots = 0
for ci, chest in ipairs(chests) do
if onProgress then onProgress(ci, #chests, chest) end
local inv = O.wrapCached(chest)
if inv then
totalSlots = totalSlots + inv.size()
local contents = inv.list()
for slot, item in pairs(contents) do
-- Parallel inventory scanning (chunked)
local CHUNK = cfg.PARALLEL_SCAN_CHUNKS or 8
local scanData = {}
local scanFns = {}
for _, chest in ipairs(chests) do
table.insert(scanFns, function()
local inv = O.wrapCached(chest)
if inv then
scanData[chest] = {
size = inv.size(),
contents = inv.list(),
}
end
end)
end
for i = 1, #scanFns, CHUNK do
local chunk = {}
local chunkEnd = math.min(i + CHUNK - 1, #scanFns)
for j = i, chunkEnd do
chunk[#chunk + 1] = scanFns[j]
end
if onProgress then
onProgress(chunkEnd, #chests, chests[chunkEnd] or "scanning...")
end
parallel.waitForAll(table.unpack(chunk))
end
for _, chest in ipairs(chests) do
local data = scanData[chest]
if data then
totalSlots = totalSlots + data.size
for slot, item in pairs(data.contents) do
usedSlots = usedSlots + 1
if not catalogue[item.name] then
catalogue[item.name] = {}
@@ -293,6 +319,22 @@ end
-- Barrel auto-sort
-------------------------------------------------
--- Get chests sorted by priority (highest first).
-- Falls back to name order if no priority is configured.
function O.getChestsByPriority()
local chests = O.getChests()
local priority = cfg.CHEST_PRIORITY
if not priority or not next(priority) then return chests end
local sorted = { table.unpack(chests) }
table.sort(sorted, function(a, b)
local pa = priority[a] or 0
local pb = priority[b] or 0
if pa ~= pb then return pa > pb end
return a < b
end)
return sorted
end
function O.sortBarrel(barrelOverride)
local barrelTarget = (barrelOverride and barrelOverride ~= "") and barrelOverride or cfg.BARREL_NAME
local barrel = O.wrapCached(barrelTarget)
@@ -305,7 +347,7 @@ function O.sortBarrel(barrelOverride)
state.needsRedraw = true
local catalogue = cache.catalogue
local chests = O.getChests()
local chests = O.getChestsByPriority()
for slot, item in pairs(contents) do
local moved = 0
@@ -751,6 +793,63 @@ function O.checkAlerts()
end
end
-------------------------------------------------
-- Supply chest (builder / manifest-based stocking)
-------------------------------------------------
function O.supplyChest()
if cfg.SUPPLY_CHEST == "" or #cfg.SUPPLY_MANIFEST == 0 then return false end
local supply = O.wrapCached(cfg.SUPPLY_CHEST)
if not supply then return false end
-- Scan what's already in the supply chest
local existing = {}
local contents = supply.list()
if contents then
for _, item in pairs(contents) do
existing[item.name] = (existing[item.name] or 0) + item.count
end
end
local catalogue = cache.catalogue
local didWork = false
for _, manifest in ipairs(cfg.SUPPLY_MANIFEST) do
local have = existing[manifest.name] or 0
local want = manifest.count or 0
local deficit = want - have
if deficit > 0 and catalogue[manifest.name] then
local remaining = deficit
local srcSnapshot = { table.unpack(catalogue[manifest.name]) }
for _, source in ipairs(srcSnapshot) do
if source.total > 0 then
local chest = O.wrapCached(source.chest)
if chest then
for slot, slotItem in pairs(chest.list()) do
if slotItem.name == manifest.name then
local toMove = math.min(slotItem.count, remaining)
local n = chest.pushItems(cfg.SUPPLY_CHEST, slot, toMove)
if n and n > 0 then
state.adjustCache(manifest.name, source.chest, -n)
remaining = remaining - n
didWork = true
log.info("SUPPLY", "%s x%d -> %s", manifest.name, n, cfg.SUPPLY_CHEST)
if remaining <= 0 then break end
end
end
end
end
end
if remaining <= 0 then break end
end
end
end
return didWork
end
-------------------------------------------------
-- Order / Dispense
-------------------------------------------------
@@ -1012,6 +1111,24 @@ function O.craftItem(recipeIdx)
end
end
-------------------------------------------------
-- Recursive crafting (multi-step chains)
-------------------------------------------------
function O.recursiveCraft(outputName, count)
if not ctx.craftEngine then
return false, "Craft engine not initialized"
end
activity.crafting = true
state.needsRedraw = true
state.smelterNeedsRedraw = true
local ok, err = ctx.craftEngine.executeChain(outputName, count, ctx)
activity.crafting = false
state.needsRedraw = true
state.smelterNeedsRedraw = true
return ok, err
end
-------------------------------------------------
-- Smelting recipe persistence
-------------------------------------------------