Add smelter dashboard functionality to display furnace status and recipes
This commit is contained in:
@@ -829,6 +829,309 @@ local function drawDashboard()
|
||||
touchZones = pendingZones
|
||||
end
|
||||
|
||||
-------------------------------------------------
|
||||
-- Smelter Dashboard
|
||||
-------------------------------------------------
|
||||
|
||||
local function drawSmelterDashboard()
|
||||
if not smelterMon then return end
|
||||
|
||||
local w, h = smelterMon.getSize()
|
||||
smelterPendingZones = {}
|
||||
|
||||
-- Offscreen buffer
|
||||
draw = window.create(smelterMon, 1, 1, w, h, false)
|
||||
draw.setBackgroundColor(colors.black)
|
||||
draw.clear()
|
||||
|
||||
-- ===== Title bar =====
|
||||
monFill(1, colors.purple)
|
||||
monCenter(1, " ** SMELTER DASHBOARD ** ", colors.white, colors.purple)
|
||||
|
||||
-- ===== Status bar =====
|
||||
monFill(2, colors.gray)
|
||||
local activeCount = 0
|
||||
for _, fs in ipairs(cache.furnaceStatus or {}) do
|
||||
if fs.active then activeCount = activeCount + 1 end
|
||||
end
|
||||
local statusStr = string.format(" Furnaces: %d Active: %d",
|
||||
cache.furnaceCount or 0, activeCount)
|
||||
monWrite(2, 2, statusStr, colors.white, colors.gray)
|
||||
|
||||
-- Pause/Resume button
|
||||
local pauseLabel = smeltingPaused and " PAUSED " or " ACTIVE "
|
||||
local pauseBg = smeltingPaused and colors.red or colors.lime
|
||||
local pauseFg = smeltingPaused and colors.white or colors.black
|
||||
monWrite(w - #pauseLabel, 2, pauseLabel, pauseFg, pauseBg)
|
||||
addSmelterZone(w - #pauseLabel, 2, w - 1, 2, "toggle_pause", nil)
|
||||
|
||||
-- ===== Divider =====
|
||||
monFill(3, colors.magenta)
|
||||
monCenter(3, string.rep("-", math.min(w - 4, 60)), colors.pink, colors.magenta)
|
||||
|
||||
-- ===== Tab row =====
|
||||
monFill(4, colors.black)
|
||||
local tabStatusBg = smelterView == "status" and colors.purple or colors.gray
|
||||
local tabRecipesBg = smelterView == "recipes" and colors.purple or colors.gray
|
||||
local bx1, by1, bx2, by2
|
||||
bx1, by1, bx2, by2 = drawButton(2, 4, "Status", colors.white, tabStatusBg)
|
||||
addSmelterZone(bx1, by1, bx2, by2, "tab", "status")
|
||||
|
||||
bx1, by1, bx2, by2 = drawButton(bx2 + 2, 4, "Recipes", colors.white, tabRecipesBg)
|
||||
addSmelterZone(bx1, by1, bx2, by2, "tab", "recipes")
|
||||
|
||||
if smelterView == "status" then
|
||||
-- ===== Furnace Status View =====
|
||||
-- Column headers
|
||||
monFill(5, colors.gray)
|
||||
local outCol = math.floor(w * 0.40)
|
||||
local fuelCol = math.floor(w * 0.65)
|
||||
local statCol = w - 6
|
||||
monWrite(2, 5, "#", colors.lightGray, colors.gray)
|
||||
monWrite(4, 5, "T", colors.lightGray, colors.gray)
|
||||
monWrite(6, 5, "Input", colors.lightGray, colors.gray)
|
||||
monWrite(outCol, 5, "Output", colors.lightGray, colors.gray)
|
||||
monWrite(fuelCol, 5, "Fuel", colors.lightGray, colors.gray)
|
||||
monWrite(statCol, 5, "State", colors.lightGray, colors.gray)
|
||||
|
||||
-- Furnace rows
|
||||
local furnaceList = cache.furnaceStatus or {}
|
||||
local maxRows = h - 8
|
||||
if maxRows < 1 then maxRows = 1 end
|
||||
smelterTotalPages = math.max(1, math.ceil(#furnaceList / maxRows))
|
||||
if smelterPage > smelterTotalPages then smelterPage = smelterTotalPages end
|
||||
if smelterPage < 1 then smelterPage = 1 end
|
||||
|
||||
local startIdx = (smelterPage - 1) * maxRows + 1
|
||||
local endIdx = math.min(startIdx + maxRows - 1, #furnaceList)
|
||||
|
||||
local row = 6
|
||||
if #furnaceList == 0 then
|
||||
monFill(7, colors.black)
|
||||
monCenter(7, "No furnaces found on network", colors.gray, colors.black)
|
||||
row = 8
|
||||
else
|
||||
for i = startIdx, endIdx do
|
||||
local fs = furnaceList[i]
|
||||
local y = row
|
||||
local rowBg = ((i - startIdx) % 2 == 0) and colors.black or colors.gray
|
||||
monFill(y, rowBg)
|
||||
|
||||
-- Number
|
||||
monWrite(2, y, string.format("%d", i), colors.lightBlue, rowBg)
|
||||
|
||||
-- Type abbreviation
|
||||
local typeAbbr = "F"
|
||||
local typeColor = colors.orange
|
||||
if fs.type == "minecraft:smoker" then
|
||||
typeAbbr = "S"
|
||||
typeColor = colors.green
|
||||
elseif fs.type == "minecraft:blast_furnace" then
|
||||
typeAbbr = "B"
|
||||
typeColor = colors.cyan
|
||||
end
|
||||
monWrite(4, y, typeAbbr, typeColor, rowBg)
|
||||
|
||||
-- Input
|
||||
if fs.input then
|
||||
local inName = fs.input.name:gsub("^minecraft:", ""):gsub("_", " ")
|
||||
local maxIn = outCol - 8
|
||||
if #inName > maxIn then inName = inName:sub(1, maxIn - 2) .. ".." end
|
||||
monWrite(6, y, inName, colors.white, rowBg)
|
||||
monWrite(outCol - 4, y, "x" .. fs.input.count, colors.yellow, rowBg)
|
||||
else
|
||||
monWrite(6, y, "(empty)", colors.lightGray, rowBg)
|
||||
end
|
||||
|
||||
-- Output
|
||||
if fs.output then
|
||||
local outName = fs.output.name:gsub("^minecraft:", ""):gsub("_", " ")
|
||||
local maxOut = fuelCol - outCol - 5
|
||||
if #outName > maxOut then outName = outName:sub(1, maxOut - 2) .. ".." end
|
||||
monWrite(outCol, y, outName, colors.white, rowBg)
|
||||
monWrite(fuelCol - 4, y, "x" .. fs.output.count, colors.yellow, rowBg)
|
||||
else
|
||||
monWrite(outCol, y, "-", colors.lightGray, rowBg)
|
||||
end
|
||||
|
||||
-- Fuel
|
||||
if fs.fuel then
|
||||
local fuelName = fs.fuel.name:gsub("^minecraft:", ""):gsub("_", " ")
|
||||
local maxFuel = statCol - fuelCol - 4
|
||||
if #fuelName > maxFuel then fuelName = fuelName:sub(1, maxFuel - 2) .. ".." end
|
||||
monWrite(fuelCol, y, fuelName, colors.white, rowBg)
|
||||
monWrite(statCol - 4, y, "x" .. fs.fuel.count, colors.yellow, rowBg)
|
||||
else
|
||||
monWrite(fuelCol, y, "-", colors.lightGray, rowBg)
|
||||
end
|
||||
|
||||
-- Status indicator
|
||||
if smeltingPaused then
|
||||
monWrite(statCol, y, "PAUSE", colors.red, rowBg)
|
||||
elseif fs.active then
|
||||
monWrite(statCol, y, " COOK", colors.lime, rowBg)
|
||||
elseif fs.input and not fs.fuel then
|
||||
monWrite(statCol, y, "FUEL?", colors.orange, rowBg)
|
||||
else
|
||||
monWrite(statCol, y, " IDLE", colors.lightGray, rowBg)
|
||||
end
|
||||
|
||||
row = row + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill remaining rows
|
||||
while row <= h - 2 do
|
||||
monFill(row, colors.black)
|
||||
row = row + 1
|
||||
end
|
||||
|
||||
else
|
||||
-- ===== Recipe Manager View =====
|
||||
|
||||
-- Build sorted recipe list
|
||||
local recipeList = {}
|
||||
for inputName, recipe in pairs(SMELTABLE) do
|
||||
local short = inputName:gsub("^minecraft:", ""):gsub("_", " ")
|
||||
short = short:sub(1,1):upper() .. short:sub(2)
|
||||
local resultShort = recipe.result:gsub("^minecraft:", ""):gsub("_", " ")
|
||||
resultShort = resultShort:sub(1,1):upper() .. resultShort:sub(2)
|
||||
local types = ""
|
||||
for _, ft in ipairs(recipe.furnaces) do
|
||||
if ft == "minecraft:furnace" then types = types .. "F"
|
||||
elseif ft == "minecraft:smoker" then types = types .. "S"
|
||||
elseif ft == "minecraft:blast_furnace" then types = types .. "B"
|
||||
end
|
||||
end
|
||||
local enabled = not disabledRecipes[inputName]
|
||||
local inStorage = 0
|
||||
if cache.catalogue[inputName] then
|
||||
for _, s in ipairs(cache.catalogue[inputName]) do
|
||||
inStorage = inStorage + s.total
|
||||
end
|
||||
end
|
||||
table.insert(recipeList, {
|
||||
inputName = inputName,
|
||||
inputShort = short,
|
||||
resultShort = resultShort,
|
||||
types = types,
|
||||
enabled = enabled,
|
||||
inStorage = inStorage,
|
||||
})
|
||||
end
|
||||
table.sort(recipeList, function(a, b) return a.inputShort < b.inputShort end)
|
||||
|
||||
-- Column positions
|
||||
local arrowCol = math.floor(w * 0.30)
|
||||
local typeCol = math.floor(w * 0.60)
|
||||
local stockCol = math.floor(w * 0.72)
|
||||
local toggleCol = w - 5
|
||||
|
||||
-- Column headers
|
||||
monFill(5, colors.gray)
|
||||
monWrite(2, 5, "Input", colors.lightGray, colors.gray)
|
||||
monWrite(arrowCol, 5, "Output", colors.lightGray, colors.gray)
|
||||
monWrite(typeCol, 5, "Type", colors.lightGray, colors.gray)
|
||||
monWrite(stockCol, 5, "Stock", colors.lightGray, colors.gray)
|
||||
monWrite(toggleCol, 5, "On?", colors.lightGray, colors.gray)
|
||||
|
||||
-- Bulk action buttons on tab row
|
||||
local bulkX = w - 22
|
||||
bx1, by1, bx2, by2 = drawButton(bulkX, 4, "All On", colors.white, colors.green)
|
||||
addSmelterZone(bx1, by1, bx2, by2, "enable_all", nil)
|
||||
bx1, by1, bx2, by2 = drawButton(bx2 + 2, 4, "All Off", colors.white, colors.red)
|
||||
addSmelterZone(bx1, by1, bx2, by2, "disable_all", nil)
|
||||
|
||||
-- Recipe rows
|
||||
local maxRows = h - 8
|
||||
if maxRows < 1 then maxRows = 1 end
|
||||
smelterTotalPages = math.max(1, math.ceil(#recipeList / maxRows))
|
||||
if smelterPage > smelterTotalPages then smelterPage = smelterTotalPages end
|
||||
if smelterPage < 1 then smelterPage = 1 end
|
||||
|
||||
local startIdx = (smelterPage - 1) * maxRows + 1
|
||||
local endIdx = math.min(startIdx + maxRows - 1, #recipeList)
|
||||
|
||||
local row = 6
|
||||
for i = startIdx, endIdx do
|
||||
local r = recipeList[i]
|
||||
local y = row
|
||||
local rowBg = ((i - startIdx) % 2 == 0) and colors.black or colors.gray
|
||||
monFill(y, rowBg)
|
||||
|
||||
-- Input name
|
||||
local maxInputLen = arrowCol - 3
|
||||
local inputDisplay = r.inputShort
|
||||
if #inputDisplay > maxInputLen then
|
||||
inputDisplay = inputDisplay:sub(1, maxInputLen - 2) .. ".."
|
||||
end
|
||||
monWrite(2, y, inputDisplay, colors.white, rowBg)
|
||||
|
||||
-- Output
|
||||
local maxOutLen = typeCol - arrowCol - 2
|
||||
local outDisplay = r.resultShort
|
||||
if #outDisplay > maxOutLen then
|
||||
outDisplay = outDisplay:sub(1, maxOutLen - 2) .. ".."
|
||||
end
|
||||
monWrite(arrowCol, y, outDisplay, colors.lightBlue, rowBg)
|
||||
|
||||
-- Types
|
||||
monWrite(typeCol, y, r.types, colors.orange, rowBg)
|
||||
|
||||
-- Stock
|
||||
monWrite(stockCol, y, tostring(r.inStorage), colors.yellow, rowBg)
|
||||
|
||||
-- Toggle button
|
||||
if r.enabled then
|
||||
monWrite(toggleCol, y, " ON ", colors.white, colors.green)
|
||||
else
|
||||
monWrite(toggleCol, y, " OFF", colors.white, colors.red)
|
||||
end
|
||||
addSmelterZone(1, y, w, y, "toggle_recipe", r.inputName)
|
||||
|
||||
row = row + 1
|
||||
end
|
||||
|
||||
-- Fill remaining rows
|
||||
while row <= h - 2 do
|
||||
monFill(row, colors.black)
|
||||
row = row + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- ===== Pagination (h - 1) =====
|
||||
monFill(h - 1, colors.gray)
|
||||
local pageStr = string.format("Pg %d/%d", smelterPage, smelterTotalPages)
|
||||
monCenter(h - 1, pageStr, colors.white, colors.gray)
|
||||
|
||||
if smelterPage > 1 then
|
||||
monWrite(2, h - 1, " < ", colors.white, colors.lightGray)
|
||||
addSmelterZone(2, h - 1, 4, h - 1, "page_prev", nil)
|
||||
end
|
||||
if smelterPage < smelterTotalPages then
|
||||
monWrite(w - 3, h - 1, " > ", colors.white, colors.lightGray)
|
||||
addSmelterZone(w - 3, h - 1, w - 1, h - 1, "page_next", nil)
|
||||
end
|
||||
|
||||
-- ===== Bottom accent =====
|
||||
monFill(h, colors.purple)
|
||||
local enabledCount = 0
|
||||
local totalRecipes = 0
|
||||
for _ in pairs(SMELTABLE) do totalRecipes = totalRecipes + 1 end
|
||||
for inputName in pairs(SMELTABLE) do
|
||||
if not disabledRecipes[inputName] then enabledCount = enabledCount + 1 end
|
||||
end
|
||||
local bottomMsg = string.format(" Recipes: %d/%d enabled ", enabledCount, totalRecipes)
|
||||
if activity.smelting then bottomMsg = " SMELTING... " end
|
||||
monCenter(h, bottomMsg, colors.pink, colors.purple)
|
||||
|
||||
-- Flush to monitor
|
||||
draw.setVisible(true)
|
||||
|
||||
-- Swap zones
|
||||
smelterTouchZones = smelterPendingZones
|
||||
end
|
||||
|
||||
-------------------------------------------------
|
||||
-- Barrel auto-sort
|
||||
-------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user