feat: implement parallel inventory scanning and supply chest functionality
This commit is contained in:
@@ -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
|
||||
-------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user