Add smelter dashboard functionality and manage disabled recipes
This commit is contained in:
@@ -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)
|
||||
-------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user