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 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
|
||||||
|
|||||||
Reference in New Issue
Block a user