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