Enhance autoSmelt function for balanced distribution of smeltable items across empty furnaces

This commit is contained in:
MayaTheShy
2026-03-16 20:51:13 -04:00
parent 9e1852a219
commit 32eaa2db3d

View File

@@ -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