diff --git a/inventoryManager.lua b/inventoryManager.lua index 09a5ef9..adba00b 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -6,6 +6,98 @@ local BARREL_NAME = "minecraft:barrel_0" local POLL_INTERVAL = 2 -- seconds between barrel checks local MONITOR_SIDE = "left" local SCAN_INTERVAL = 3 -- seconds between background scans +local SMELT_INTERVAL = 3 -- seconds between furnace checks +local SMELT_RESERVE = 64 -- keep at least 1 stack of each raw material + +------------------------------------------------- +-- Furnace types to manage +------------------------------------------------- + +local FURNACE_TYPES = { + "minecraft:furnace", + "minecraft:smoker", + "minecraft:blast_furnace", +} + +-- Furnace slots: 1 = input, 2 = fuel, 3 = output (standard Minecraft) +local SLOT_INPUT = 1 +local SLOT_FUEL = 2 +local SLOT_OUTPUT = 3 + +------------------------------------------------- +-- Smeltable items: input -> output +-- Items in chests matching a key here get auto-smelted. +-- Add/remove entries to control what gets cooked. +------------------------------------------------- + +local SMELTABLE = { + -- Ores + ["minecraft:raw_iron"] = "minecraft:iron_ingot", + ["minecraft:raw_gold"] = "minecraft:gold_ingot", + ["minecraft:raw_copper"] = "minecraft:copper_ingot", + ["minecraft:iron_ore"] = "minecraft:iron_ingot", + ["minecraft:gold_ore"] = "minecraft:gold_ingot", + ["minecraft:copper_ore"] = "minecraft:copper_ingot", + ["minecraft:deepslate_iron_ore"] = "minecraft:iron_ingot", + ["minecraft:deepslate_gold_ore"] = "minecraft:gold_ingot", + ["minecraft:deepslate_copper_ore"] = "minecraft:copper_ingot", + ["minecraft:ancient_debris"] = "minecraft:netherite_scrap", + -- Sand / stone + ["minecraft:sand"] = "minecraft:glass", + ["minecraft:red_sand"] = "minecraft:glass", + ["minecraft:cobblestone"] = "minecraft:stone", + ["minecraft:stone"] = "minecraft:smooth_stone", + ["minecraft:clay_ball"] = "minecraft:brick", + ["minecraft:netherrack"] = "minecraft:nether_brick", + ["minecraft:sandstone"] = "minecraft:smooth_sandstone", + -- Food + ["minecraft:beef"] = "minecraft:cooked_beef", + ["minecraft:porkchop"] = "minecraft:cooked_porkchop", + ["minecraft:chicken"] = "minecraft:cooked_chicken", + ["minecraft:mutton"] = "minecraft:cooked_mutton", + ["minecraft:rabbit"] = "minecraft:cooked_rabbit", + ["minecraft:cod"] = "minecraft:cooked_cod", + ["minecraft:salmon"] = "minecraft:cooked_salmon", + ["minecraft:potato"] = "minecraft:baked_potato", + ["minecraft:kelp"] = "minecraft:dried_kelp", + -- Misc + ["minecraft:wet_sponge"] = "minecraft:sponge", + ["minecraft:cactus"] = "minecraft:green_dye", + ["minecraft:sea_pickle"] = "minecraft:lime_dye", + ["minecraft:log"] = "minecraft:charcoal", + ["minecraft:oak_log"] = "minecraft:charcoal", + ["minecraft:spruce_log"] = "minecraft:charcoal", + ["minecraft:birch_log"] = "minecraft:charcoal", + ["minecraft:jungle_log"] = "minecraft:charcoal", + ["minecraft:acacia_log"] = "minecraft:charcoal", + ["minecraft:dark_oak_log"] = "minecraft:charcoal", + ["minecraft:mangrove_log"] = "minecraft:charcoal", + ["minecraft:cherry_log"] = "minecraft:charcoal", +} + +-- Fuel items, ordered by preference (best first) +-- burn_time = how many items one fuel smelts +local FUEL_LIST = { + { name = "minecraft:coal", burn_time = 8 }, + { name = "minecraft:charcoal", burn_time = 8 }, + { name = "minecraft:coal_block", burn_time = 80 }, + { name = "minecraft:blaze_rod", burn_time = 12 }, + { name = "minecraft:dried_kelp_block", burn_time = 20 }, + { name = "minecraft:lava_bucket", burn_time = 100 }, + { name = "minecraft:oak_planks", burn_time = 1.5 }, + { name = "minecraft:spruce_planks",burn_time = 1.5 }, + { name = "minecraft:birch_planks", burn_time = 1.5 }, + { name = "minecraft:jungle_planks",burn_time = 1.5 }, + { name = "minecraft:acacia_planks",burn_time = 1.5 }, + { name = "minecraft:dark_oak_planks",burn_time = 1.5 }, + { name = "minecraft:mangrove_planks",burn_time = 1.5 }, + { name = "minecraft:cherry_planks",burn_time = 1.5 }, + { name = "minecraft:stick", burn_time = 0.5 }, +} + +-- Build a set for quick lookup +local FUEL_SET = {} +for _, f in ipairs(FUEL_LIST) do FUEL_SET[f.name] = true end ------------------------------------------------- -- Cached data (updated by background scanner) @@ -32,6 +124,7 @@ local activity = { sorting = false, -- barrel sort in progress dispensing = false, -- order in progress scanning = false, -- background scan in progress + smelting = false, -- auto-smelt in progress } ------------------------------------------------- @@ -48,6 +141,18 @@ local function getChests() return chests end +local function getFurnaces() + local furnaces = {} + for _, ftype in ipairs(FURNACE_TYPES) do + for _, name in ipairs(peripheral.getNames()) do + if peripheral.getType(name) == ftype then + table.insert(furnaces, name) + end + end + end + return furnaces +end + local function scanInventory(deviceName) local inv = peripheral.wrap(deviceName) if not inv then return {} end @@ -120,6 +225,17 @@ local function refreshCache() cache.dropperOk = peripheral.wrap(DROPPER_NAME) ~= nil cache.barrelOk = peripheral.wrap(BARREL_NAME) ~= nil + -- Count furnaces + local furnaceCount = 0 + for _, ftype in ipairs(FURNACE_TYPES) do + for _, name in ipairs(peripheral.getNames()) do + if peripheral.getType(name) == ftype then + furnaceCount = furnaceCount + 1 + end + end + end + cache.furnaceCount = furnaceCount + activity.scanning = false end @@ -274,11 +390,15 @@ local function drawDashboard() table.insert(statusParts, string.format(" Chests: %d", cache.chestCount)) table.insert(statusParts, cache.dropperOk and "Dropper: OK" or "Dropper: --") table.insert(statusParts, cache.barrelOk and "Barrel: OK" or "Barrel: --") + if cache.furnaceCount and cache.furnaceCount > 0 then + table.insert(statusParts, string.format("Furnaces: %d", cache.furnaceCount)) + end -- Activity indicators local actParts = {} if activity.sorting then table.insert(actParts, "SORTING") end if activity.dispensing then table.insert(actParts, "DISPENSING") end + if activity.smelting then table.insert(actParts, "SMELTING") end if activity.scanning then table.insert(actParts, "SCANNING") end monWrite(2, 2, table.concat(statusParts, " | "), colors.white, colors.gray) @@ -528,6 +648,8 @@ local function drawDashboard() local bottomMsg = " Tap item to order " if activity.dispensing then bottomMsg = " DISPENSING... " + elseif activity.smelting then + bottomMsg = " SMELTING... " elseif activity.sorting then bottomMsg = " SORTING BARREL... " end @@ -592,6 +714,122 @@ local function sortBarrel() needsRedraw = true end +------------------------------------------------- +-- Auto-smelt +------------------------------------------------- + +local function autoSmelt() + local furnaces = getFurnaces() + if #furnaces == 0 then return end + + local chests = getChests() + local catalogue = cache.catalogue + local didWork = false + + for _, fname in ipairs(furnaces) do + local furnace = peripheral.wrap(fname) + if furnace then + local contents = furnace.list() + + -- 1) Pull finished output (slot 3) back to chests + if contents[SLOT_OUTPUT] then + for _, chest in ipairs(chests) do + local n = furnace.pushItems(chest, SLOT_OUTPUT) + if n and n > 0 then + print(string.format("[SMELT] Output %s x%d -> %s", + contents[SLOT_OUTPUT].name, n, chest)) + didWork = true + break + end + end + end + + -- Re-read after output pull + contents = furnace.list() + + -- 2) Refuel if fuel slot is empty or low + local fuelItem = contents[SLOT_FUEL] + local needFuel = not fuelItem or fuelItem.count < 8 + + if needFuel then + for _, fuel in ipairs(FUEL_LIST) do + if catalogue[fuel.name] then + for _, source in ipairs(catalogue[fuel.name]) do + local chest = peripheral.wrap(source.chest) + if chest then + for slot, slotItem in pairs(chest.list()) do + if slotItem.name == fuel.name then + local toMove = math.min(16, slotItem.count) + local n = chest.pushItems(fname, slot, toMove, SLOT_FUEL) + if n and n > 0 then + print(string.format("[SMELT] Fuel %s x%d -> %s", + fuel.name, n, fname)) + didWork = true + needFuel = false + break + end + end + end + end + if not needFuel then break end + end + end + if not needFuel then break end + end + end + + -- 3) Load smeltable items into empty input slot + local inputItem = contents[SLOT_INPUT] + if not inputItem then + -- Find something smeltable in chests + for itemName, _ in pairs(SMELTABLE) do + if 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 + + -- Only smelt the excess beyond SMELT_RESERVE + local available = totalInStorage - SMELT_RESERVE + if available <= 0 then + -- Skip: need to keep reserve + else + 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) + if n and n > 0 then + print(string.format("[SMELT] Input %s x%d -> %s (reserve %d)", + itemName, n, fname, math.max(0, totalInStorage - n))) + didWork = true + remaining = remaining - n + if remaining <= 0 then + loaded = true + break + end + end + end + end + end + if loaded then break end + end + if loaded or remaining < math.min(available, 64) then break end + end + end + end + end + end + end + + return didWork +end + ------------------------------------------------- -- Order ------------------------------------------------- @@ -801,7 +1039,24 @@ local function main() end end, - -- Task 3: Dashboard redraw (event-driven, checks every 0.1s) + -- Task 3: Auto-smelt + function() + while true do + activity.smelting = true + needsRedraw = true + local ok, didWork = pcall(autoSmelt) + activity.smelting = false + needsRedraw = true + -- If work was done, scan sooner to update cache + if ok and didWork then + pcall(refreshCache) + needsRedraw = true + end + sleep(SMELT_INTERVAL) + end + end, + + -- Task 4: Dashboard redraw (event-driven, checks every 0.1s) function() needsRedraw = true while true do @@ -821,7 +1076,7 @@ local function main() end end, - -- Task 4: Touch event listener + -- Task 5: Touch event listener function() while true do local event, side, x, y = os.pullEvent("monitor_touch")