Enhance autoSmelt function for balanced distribution of smeltable items across empty furnaces
This commit is contained in:
@@ -2267,6 +2267,7 @@ local function autoSmelt()
|
||||
local chests = getChests()
|
||||
local catalogue = cache.catalogue
|
||||
local didWork = false
|
||||
local emptyInputFurnaces = {} -- collected during steps 1-3, filled in step 5
|
||||
|
||||
for _, fname in ipairs(furnaces) do
|
||||
local furnace = peripheral.wrap(fname)
|
||||
@@ -2369,40 +2370,80 @@ local function autoSmelt()
|
||||
end
|
||||
end
|
||||
|
||||
-- 4) Load smeltable items into empty input slot
|
||||
-- 4) Collect furnaces with empty input for balanced loading below
|
||||
inputItem = contents[SLOT_INPUT]
|
||||
if not inputItem then
|
||||
-- Use pre-built candidate list (already sorted: food first, then alpha)
|
||||
local candidates = smeltCandidatesByType[furnaceType] or {}
|
||||
table.insert(emptyInputFurnaces, { name = fname, type = furnaceType })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Try each candidate
|
||||
for _, cand in ipairs(candidates) do
|
||||
local itemName = cand.name
|
||||
if not disabledRecipes[itemName] and catalogue[itemName] then
|
||||
-- Count total of this item across all chests
|
||||
local totalInStorage = 0
|
||||
for _, src in ipairs(catalogue[itemName]) do
|
||||
totalInStorage = totalInStorage + src.total
|
||||
end
|
||||
-- 5) Balanced distribution of smeltable items across all empty furnaces
|
||||
-- Instead of greedily filling one furnace at a time, we spread items
|
||||
-- evenly so all compatible furnaces work in parallel.
|
||||
if #emptyInputFurnaces > 0 then
|
||||
-- Build a unified, deduplicated candidate list across all empty furnace types
|
||||
local typesSeen = {}
|
||||
for _, ef in ipairs(emptyInputFurnaces) do typesSeen[ef.type] = true end
|
||||
|
||||
-- Only smelt the excess beyond SMELT_RESERVE
|
||||
local available = totalInStorage - SMELT_RESERVE
|
||||
if available > 0 then
|
||||
local allCandidates = {}
|
||||
local candSeen = {}
|
||||
for ftype in pairs(typesSeen) do
|
||||
for _, cand in ipairs(smeltCandidatesByType[ftype] or {}) do
|
||||
if not candSeen[cand.name] then
|
||||
candSeen[cand.name] = true
|
||||
table.insert(allCandidates, cand)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Sort: food first, then alphabetical (same priority as before)
|
||||
table.sort(allCandidates, function(a, b)
|
||||
if a.food ~= b.food then return a.food end
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
local usedFurnaces = {} -- furnaces already assigned an item
|
||||
|
||||
for _, cand in ipairs(allCandidates) do
|
||||
local itemName = cand.name
|
||||
if not disabledRecipes[itemName] and catalogue[itemName] then
|
||||
-- Find all compatible empty furnaces not yet used
|
||||
local compatFurnaces = {}
|
||||
for _, ef in ipairs(emptyInputFurnaces) do
|
||||
if not usedFurnaces[ef.name] and cand.recipe.furnaceSet[ef.type] then
|
||||
table.insert(compatFurnaces, ef)
|
||||
end
|
||||
end
|
||||
|
||||
if #compatFurnaces > 0 then
|
||||
local totalInStorage = 0
|
||||
for _, src in ipairs(catalogue[itemName]) do
|
||||
totalInStorage = totalInStorage + src.total
|
||||
end
|
||||
local available = totalInStorage - SMELT_RESERVE
|
||||
if available > 0 then
|
||||
local perFurnace = math.min(64, math.ceil(available / #compatFurnaces))
|
||||
|
||||
for _, ef in ipairs(compatFurnaces) do
|
||||
if available <= 0 then break end
|
||||
local toLoad = math.min(perFurnace, available)
|
||||
local remaining = toLoad
|
||||
local loaded = false
|
||||
local remaining = math.min(available, 64)
|
||||
|
||||
for _, source in ipairs(catalogue[itemName]) do
|
||||
local chest = peripheral.wrap(source.chest)
|
||||
if chest then
|
||||
for slot, slotItem in pairs(chest.list()) do
|
||||
if slotItem.name == itemName then
|
||||
local toMove = math.min(slotItem.count, remaining)
|
||||
local n = chest.pushItems(fname, slot, toMove, SLOT_INPUT)
|
||||
local n = chest.pushItems(ef.name, slot, toMove, SLOT_INPUT)
|
||||
if n and n > 0 then
|
||||
adjustCache(itemName, source.chest, -n)
|
||||
print(string.format("[SMELT] Input %s x%d -> %s (reserve %d)",
|
||||
itemName, n, fname, math.max(0, totalInStorage - n)))
|
||||
print(string.format("[SMELT] Input %s x%d -> %s (balanced %d/furnace)",
|
||||
itemName, n, ef.name, perFurnace))
|
||||
didWork = true
|
||||
remaining = remaining - n
|
||||
available = available - n
|
||||
if remaining <= 0 then
|
||||
loaded = true
|
||||
break
|
||||
@@ -2413,7 +2454,10 @@ local function autoSmelt()
|
||||
end
|
||||
if loaded then break end
|
||||
end
|
||||
if loaded or remaining < math.min(available, 64) then break end
|
||||
|
||||
if loaded or remaining < toLoad then
|
||||
usedFurnaces[ef.name] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user