--furnacemonitor.lua --(( Settings ))-- local textScale = 0.5 ---@class FurnaceMonitorSides ---@field topFurn string ---@field monitor string ---@field botFurn string local _ ---@type FurnaceMonitorSides[] local furnaceMonitorSides = { { topFurn = "minecraft:furnace_11817", monitor = "monitor_4475", botFurn = "minecraft:furnace_11810", }, { topFurn = "minecraft:furnace_11815", monitor = "monitor_4473", botFurn = "minecraft:furnace_11812", }, { topFurn = "minecraft:furnace_11813", monitor = "monitor_4474", botFurn = "minecraft:furnace_11809", }, { topFurn = "minecraft:furnace_11818", monitor = "monitor_4476", botFurn = "minecraft:furnace_11819", }, { topFurn = "minecraft:furnace_11820", monitor = "monitor_4477", botFurn = "minecraft:furnace_11821", }, { topFurn = "minecraft:furnace_11822", monitor = "monitor_4478", botFurn = "minecraft:furnace_11823", }, } --(( Types & Static variables ))-- local furnaceBurnableSlot = 1 local furnaceFuelSlot = 2 local furnaceResultSlot = 3 local ticksPerSecond = 20 local ticksPerCookedItem = 10 * ticksPerSecond local orientation = { top = 0, bottom = 1, } ---@class FurnaceMonitor ---@field furn quarkFurnace ---@field redirect Redirect ---@field orientation integer local _ --(( Functions ))-- ---@param periphType string ---@param side string ---@return Peripheral local function getPeripheralOfType(periphType, side) local actualType = peripheral.getType(side) local periph = peripheral.wrap(side) if not actualType or not periph then error(string.format("Expected %s at '%s', got nil.", periphType, side)) end if actualType ~= periphType then error(string.format("Expected %s at '%s', got %s.", periphType, side, actualType)) end return periph end ---@param side string ---@return Monitor local function getMonitor(side) return getPeripheralOfType("monitor", side) end ---@param side string ---@return quarkFurnace local function getFurnace(side) return getPeripheralOfType("minecraft:furnace", side) end ---@param furn quarkFurnace ---@param redirect Redirect ---@param orientation integer ---@return FurnaceMonitor local function createFurnMon(furn, redirect, orientation) ---@type FurnaceMonitor local furnMon = {} furnMon.furn = furn furnMon.redirect = redirect furnMon.orientation = orientation return furnMon end ---@param source Redirect ---@param windowHeight integer ---@return Window,Window local function createWindows(source, windowHeight) local maxW,maxH = source.getSize() local botY = maxH - windowHeight + 1 local topWindow = window.create( source, 1, 1, maxW, windowHeight ) local botWindow = window.create( source, 1, botY, maxW, windowHeight ) return topWindow, botWindow end ---@param col1 string ---@param col2 string ---@param barWidth integer ---@param fullWidth integer local function getBlittableBarColors(col1, col2, barWidth, fullWidth) return col1:rep(barWidth) .. col2:rep(fullWidth - barWidth) end ---@param r Redirect ---@param title string ---@param x integer ---@param y integer ---@param width integer ---@param ticksPassed integer ---@param ticksTotal integer ---@param rounding fun(ticks:number):integer local function drawTicksProgress(r, title, x, y, width, ticksPassed, ticksTotal, rounding) local perc = ticksPassed / ticksTotal if ticksTotal == 0 then perc = 0 end local barWidth = (rounding or math.ceil)(width * perc) local percX = width - #"100%" -- constructs string like: -- " 12 Coal 56% " local str = table.concat { title or "", string.rep(" ", width), }:sub(1, percX) .. string.format("%3.f%%", 100*perc) local bg = getBlittableBarColors("e", "7", barWidth, width) local fg if not title then fg = getBlittableBarColors("8", "1", barWidth, width) else fg = getBlittableBarColors("0", "1", barWidth, width) end -- draw bar r.setCursorPos(x, y) r.blit(str, fg, bg) end ---@param inv quarkInventory ---@param slot integer ---@return string|nil local function getItemDisplayName(inv, slot) ---@type quarkItemMeta local item = inv.getItemMeta(slot) if item then return string.format("%-2i %s", item.count, item. displayName) end end ---@param inv quarkInventory ---@return integer,integer local function calcResultItemCounts(inv) ---@type quarkItemMeta local resultItems = inv.getItemMeta(furnaceResultSlot) ---@type quarkItemObj local burnableItems = inv.getItemMeta(furnaceBurnableSlot) local itemCount = resultItems and resultItems.count or 0 local maxCount = math.min( resultItems and resultItems.maxCount or 0, itemCount + (burnableItems and burnableItems.count or 0) ) return itemCount, maxCount end ---@param furnMon FurnaceMonitor local function drawFurnace(furnMon) local f = furnMon.furn local r = furnMon.redirect local x = 1 local w,h = r.getSize() local barWidth = w local doneY, burnableY, fuelY, resultY = 1, 2, 4, 3 if furnMon.orientation == orientation.bottom then doneY = h end local burnable = getItemDisplayName(f, furnaceBurnableSlot) drawTicksProgress(r, burnable, x, burnableY, barWidth, f.getCookTime(), ticksPerCookedItem, math.floor) local fuel = getItemDisplayName(f, furnaceFuelSlot) drawTicksProgress(r, fuel, x, fuelY, barWidth, f.getRemainingBurnTime(), f.getBurnTime(), math.ceil) local result = getItemDisplayName(f, furnaceResultSlot) local resultItemCount, resultMaxItems = calcResultItemCounts(f) drawTicksProgress(r, result, x, resultY, barWidth, resultItemCount, resultMaxItems, math.floor) local bg = colors.black if resultItemCount == resultMaxItems and resultItemCount > 0 then bg = colors.lime end r.setBackgroundColor(bg) r.setCursorPos(1,doneY) r.write(string.rep(" ", w)) end --(( Main program ))-- ---@type FurnaceMonitor[] local furnMons = {} for _,v in pairs(furnaceMonitorSides) do ---@type FurnaceMonitorSides local sides = v local m = getMonitor(sides.monitor) local topFurn = getFurnace(sides.topFurn) local botFurn = getFurnace(sides.botFurn) m.setBackgroundColor(colors.black) m.clear() m.setTextScale(textScale) local _,h = m.getSize() local rowHeight = math.floor(h / 2) local topW,botW = createWindows(m, rowHeight) table.insert(furnMons, createFurnMon(topFurn, topW, orientation.top)) table.insert(furnMons, createFurnMon(botFurn, botW, orientation.bottom)) end while true do for _,v in ipairs(furnMons) do drawFurnace(v) end sleep(.5) end --(( EOF ))--