Add smelter dashboard functionality and manage disabled recipes

This commit is contained in:
MayaTheShy
2026-03-15 22:49:16 -04:00
parent ce430efc4d
commit 6a70298535

View File

@@ -9,6 +9,8 @@ local SCAN_INTERVAL = 3 -- seconds between background scans
local SMELT_INTERVAL = 3 -- seconds between furnace checks local SMELT_INTERVAL = 3 -- seconds between furnace checks
local SMELT_RESERVE = 64 -- keep at least 1 stack of each raw material local SMELT_RESERVE = 64 -- keep at least 1 stack of each raw material
local CACHE_FILE = ".inventory_cache" -- persistent cache file local CACHE_FILE = ".inventory_cache" -- persistent cache file
local SMELTER_MONITOR_SIDE = "top"
local DISABLED_RECIPES_FILE = ".disabled_recipes"
------------------------------------------------- -------------------------------------------------
-- Furnace types to manage -- Furnace types to manage
@@ -115,6 +117,8 @@ local cache = {
usedRatio = 0, usedRatio = 0,
dropperOk = false, dropperOk = false,
barrelOk = false, barrelOk = false,
furnaceCount = 0,
furnaceStatus = {}, -- per-furnace { name, type, input, fuel, output, active }
} }
------------------------------------------------- -------------------------------------------------
@@ -154,6 +158,27 @@ local function getFurnaces()
return furnaces return furnaces
end 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 function scanInventory(deviceName)
local inv = peripheral.wrap(deviceName) local inv = peripheral.wrap(deviceName)
if not inv then return {} end if not inv then return {} end
@@ -239,6 +264,9 @@ local function refreshCache(onProgress)
end end
cache.furnaceCount = furnaceCount cache.furnaceCount = furnaceCount
-- Scan furnace contents for smelter dashboard
refreshFurnaceStatus()
activity.scanning = false activity.scanning = false
-- Persist cache to disk -- Persist cache to disk
@@ -255,6 +283,7 @@ local function refreshCache(onProgress)
dropperOk = cache.dropperOk, dropperOk = cache.dropperOk,
barrelOk = cache.barrelOk, barrelOk = cache.barrelOk,
furnaceCount = cache.furnaceCount, furnaceCount = cache.furnaceCount,
furnaceStatus = cache.furnaceStatus,
savedAt = os.epoch("utc"), savedAt = os.epoch("utc"),
} }
local f = fs.open(CACHE_FILE, "w") local f = fs.open(CACHE_FILE, "w")
@@ -283,6 +312,7 @@ local function loadCacheFromDisk()
cache.dropperOk = data.dropperOk or false cache.dropperOk = data.dropperOk or false
cache.barrelOk = data.barrelOk or false cache.barrelOk = data.barrelOk or false
cache.furnaceCount = data.furnaceCount or 0 cache.furnaceCount = data.furnaceCount or 0
cache.furnaceStatus = data.furnaceStatus or {}
else else
error("invalid cache data") error("invalid cache data")
end end
@@ -299,18 +329,25 @@ end
------------------------------------------------- -------------------------------------------------
local mon = nil local mon = nil
local monName = nil
local smelterMon = nil
local smelterMonName = nil
local function setupMonitor() local function setupMonitor()
mon = peripheral.wrap(MONITOR_SIDE) mon = peripheral.wrap(MONITOR_SIDE)
-- If the side has a modem instead of a direct monitor, find it by type if mon and mon.setTextScale then
if mon and not mon.setTextScale then monName = MONITOR_SIDE
else
mon = nil mon = nil
end end
if not mon then if not mon then
-- Search for a monitor on the network -- Search for a monitor on the network (skip smelter side)
local name = peripheral.find("monitor") for _, name in ipairs(peripheral.getNames()) do
if name then if peripheral.getType(name) == "monitor" and name ~= SMELTER_MONITOR_SIDE then
mon = name mon = peripheral.wrap(name)
monName = name
break
end
end end
end end
if not mon then return false end if not mon then return false end
@@ -319,6 +356,29 @@ local function setupMonitor()
return true return true
end 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 -- UI State
------------------------------------------------- -------------------------------------------------
@@ -345,6 +405,41 @@ local kbRows = {
{"Z","X","C","V","B","N","M"}, {"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 -- Get items filtered by search query
local function getFilteredItems() local function getFilteredItems()
local filtered = {} local filtered = {}
@@ -377,6 +472,22 @@ local function hitTest(x, y)
return nil, nil return nil, nil
end 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) -- Drawing helpers (write to draw target)
------------------------------------------------- -------------------------------------------------