From 6a702985352b60d8c789db34c94f48f5301fa7f2 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Sun, 15 Mar 2026 22:49:16 -0400 Subject: [PATCH] Add smelter dashboard functionality and manage disabled recipes --- inventoryManager.lua | 123 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 6 deletions(-) diff --git a/inventoryManager.lua b/inventoryManager.lua index af9992a..a3234e9 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -9,6 +9,8 @@ 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 local CACHE_FILE = ".inventory_cache" -- persistent cache file +local SMELTER_MONITOR_SIDE = "top" +local DISABLED_RECIPES_FILE = ".disabled_recipes" ------------------------------------------------- -- Furnace types to manage @@ -115,6 +117,8 @@ local cache = { usedRatio = 0, dropperOk = false, barrelOk = false, + furnaceCount = 0, + furnaceStatus = {}, -- per-furnace { name, type, input, fuel, output, active } } ------------------------------------------------- @@ -154,6 +158,27 @@ local function getFurnaces() return furnaces end +local function refreshFurnaceStatus() + local furnaces = getFurnaces() + local status = {} + for _, fname in ipairs(furnaces) do + local furnace = peripheral.wrap(fname) + if furnace then + local contents = furnace.list() + local entry = { + name = fname, + type = peripheral.getType(fname), + input = contents[SLOT_INPUT] or nil, + fuel = contents[SLOT_FUEL] or nil, + output = contents[SLOT_OUTPUT] or nil, + active = (contents[SLOT_INPUT] ~= nil and contents[SLOT_FUEL] ~= nil), + } + table.insert(status, entry) + end + end + cache.furnaceStatus = status +end + local function scanInventory(deviceName) local inv = peripheral.wrap(deviceName) if not inv then return {} end @@ -239,6 +264,9 @@ local function refreshCache(onProgress) end cache.furnaceCount = furnaceCount + -- Scan furnace contents for smelter dashboard + refreshFurnaceStatus() + activity.scanning = false -- Persist cache to disk @@ -255,6 +283,7 @@ local function refreshCache(onProgress) dropperOk = cache.dropperOk, barrelOk = cache.barrelOk, furnaceCount = cache.furnaceCount, + furnaceStatus = cache.furnaceStatus, savedAt = os.epoch("utc"), } local f = fs.open(CACHE_FILE, "w") @@ -283,6 +312,7 @@ local function loadCacheFromDisk() cache.dropperOk = data.dropperOk or false cache.barrelOk = data.barrelOk or false cache.furnaceCount = data.furnaceCount or 0 + cache.furnaceStatus = data.furnaceStatus or {} else error("invalid cache data") end @@ -299,18 +329,25 @@ end ------------------------------------------------- local mon = nil +local monName = nil +local smelterMon = nil +local smelterMonName = nil local function setupMonitor() mon = peripheral.wrap(MONITOR_SIDE) - -- If the side has a modem instead of a direct monitor, find it by type - if mon and not mon.setTextScale then + if mon and mon.setTextScale then + monName = MONITOR_SIDE + else mon = nil end if not mon then - -- Search for a monitor on the network - local name = peripheral.find("monitor") - if name then - mon = name + -- Search for a monitor on the network (skip smelter side) + for _, name in ipairs(peripheral.getNames()) do + if peripheral.getType(name) == "monitor" and name ~= SMELTER_MONITOR_SIDE then + mon = peripheral.wrap(name) + monName = name + break + end end end if not mon then return false end @@ -319,6 +356,29 @@ local function setupMonitor() return true end +local function setupSmelterMonitor() + smelterMon = peripheral.wrap(SMELTER_MONITOR_SIDE) + if smelterMon and smelterMon.setTextScale then + smelterMonName = SMELTER_MONITOR_SIDE + else + smelterMon = nil + end + if not smelterMon then + -- Search for a second monitor on the network + for _, name in ipairs(peripheral.getNames()) do + if peripheral.getType(name) == "monitor" and name ~= monName then + smelterMon = peripheral.wrap(name) + smelterMonName = name + break + end + end + end + if not smelterMon then return false end + smelterMon.setTextScale(0.5) + smelterMon.clear() + return true +end + ------------------------------------------------- -- UI State ------------------------------------------------- @@ -345,6 +405,41 @@ local kbRows = { {"Z","X","C","V","B","N","M"}, } +------------------------------------------------- +-- Smelter dashboard state +------------------------------------------------- + +local smelterView = "status" -- "status" or "recipes" +local smelterPage = 1 +local smelterTotalPages = 1 +local smelterTouchZones = {} +local smelterPendingZones = {} +local smelterNeedsRedraw = true +local smeltingPaused = false +local disabledRecipes = {} -- { ["minecraft:raw_iron"] = true } + +local function loadDisabledRecipes() + if not fs.exists(DISABLED_RECIPES_FILE) then return end + pcall(function() + local f = fs.open(DISABLED_RECIPES_FILE, "r") + local raw = f.readAll() + f.close() + local data = textutils.unserialise(raw) + if type(data) == "table" then + if data.disabled then disabledRecipes = data.disabled end + if data.paused ~= nil then smeltingPaused = data.paused end + end + end) +end + +local function saveDisabledRecipes() + pcall(function() + local f = fs.open(DISABLED_RECIPES_FILE, "w") + f.write(textutils.serialise({ disabled = disabledRecipes, paused = smeltingPaused })) + f.close() + end) +end + -- Get items filtered by search query local function getFilteredItems() local filtered = {} @@ -377,6 +472,22 @@ local function hitTest(x, y) return nil, nil end +local function addSmelterZone(x1, y1, x2, y2, action, data) + table.insert(smelterPendingZones, { + x1 = x1, y1 = y1, x2 = x2, y2 = y2, + action = action, data = data + }) +end + +local function smelterHitTest(x, y) + for _, zone in ipairs(smelterTouchZones) do + if x >= zone.x1 and x <= zone.x2 and y >= zone.y1 and y <= zone.y2 then + return zone.action, zone.data + end + end + return nil, nil +end + ------------------------------------------------- -- Drawing helpers (write to draw target) -------------------------------------------------