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 totalSlots = 0
|
||||||
local usedSlots = 0
|
local usedSlots = 0
|
||||||
|
|
||||||
for ci, chest in ipairs(chests) do
|
-- Parallel inventory scanning (chunked)
|
||||||
if onProgress then onProgress(ci, #chests, chest) end
|
local CHUNK = cfg.PARALLEL_SCAN_CHUNKS or 8
|
||||||
local inv = O.wrapCached(chest)
|
local scanData = {}
|
||||||
if inv then
|
local scanFns = {}
|
||||||
totalSlots = totalSlots + inv.size()
|
for _, chest in ipairs(chests) do
|
||||||
local contents = inv.list()
|
table.insert(scanFns, function()
|
||||||
for slot, item in pairs(contents) do
|
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
|
usedSlots = usedSlots + 1
|
||||||
if not catalogue[item.name] then
|
if not catalogue[item.name] then
|
||||||
catalogue[item.name] = {}
|
catalogue[item.name] = {}
|
||||||
@@ -293,6 +319,22 @@ end
|
|||||||
-- Barrel auto-sort
|
-- 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)
|
function O.sortBarrel(barrelOverride)
|
||||||
local barrelTarget = (barrelOverride and barrelOverride ~= "") and barrelOverride or cfg.BARREL_NAME
|
local barrelTarget = (barrelOverride and barrelOverride ~= "") and barrelOverride or cfg.BARREL_NAME
|
||||||
local barrel = O.wrapCached(barrelTarget)
|
local barrel = O.wrapCached(barrelTarget)
|
||||||
@@ -305,7 +347,7 @@ function O.sortBarrel(barrelOverride)
|
|||||||
state.needsRedraw = true
|
state.needsRedraw = true
|
||||||
|
|
||||||
local catalogue = cache.catalogue
|
local catalogue = cache.catalogue
|
||||||
local chests = O.getChests()
|
local chests = O.getChestsByPriority()
|
||||||
|
|
||||||
for slot, item in pairs(contents) do
|
for slot, item in pairs(contents) do
|
||||||
local moved = 0
|
local moved = 0
|
||||||
@@ -751,6 +793,63 @@ function O.checkAlerts()
|
|||||||
end
|
end
|
||||||
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
|
-- Order / Dispense
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -1012,6 +1111,24 @@ function O.craftItem(recipeIdx)
|
|||||||
end
|
end
|
||||||
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
|
-- Smelting recipe persistence
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user