Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ME System Monitor for CC:Tweaked (Enhanced with Clock + Histograph + Events + Coroutines)
- local monitor = peripheral.find("monitor")
- local meBridge = peripheral.wrap("bottom")
- if not monitor then error("Monitor not found") end
- if not meBridge then error("ME Bridge not found") end
- monitor.setTextScale(0.5)
- local width, height = monitor.getSize()
- local expanded = nil
- local currentCPU = 1
- local blink = true
- local lastBlink = 0
- local lastUpdate = 0
- local quads = {
- {1, 1, math.floor(width/2), math.floor(height/2)},
- {math.floor(width/2)+1, 1, width, math.floor(height/2)},
- {1, math.floor(height/2)+1, math.floor(width/2), height},
- {math.floor(width/2)+1, math.floor(height/2)+1, width, height}
- }
- -- Histograph and events
- local histories = {{}, {}, {}, {}}
- local events = {}
- local MAX_HISTORY = width - 4
- local MAX_EVENTS = 5
- local function logEvent(msg)
- table.insert(events, 1, os.date("%H:%M:%S") .. " - " .. msg)
- if #events > MAX_EVENTS then table.remove(events) end
- end
- local function clearArea(x1, y1, x2, y2, color)
- monitor.setBackgroundColor(color or colors.black)
- for y = y1, y2 do
- monitor.setCursorPos(x1, y)
- monitor.write(string.rep(" ", x2 - x1 + 1))
- end
- end
- local function drawCenteredText(x1, x2, y, text, textColor, bg)
- monitor.setTextColor(textColor or colors.white)
- monitor.setBackgroundColor(bg or colors.black)
- local cx = math.floor((x1 + x2 - #text) / 2)
- monitor.setCursorPos(cx, y)
- monitor.write(text)
- end
- local function drawBorder(x1, y1, x2, y2, color)
- monitor.setBackgroundColor(color)
- for x = x1, x2 do
- monitor.setCursorPos(x, y1) monitor.write(" ")
- monitor.setCursorPos(x, y2) monitor.write(" ")
- end
- for y = y1 + 1, y2 - 1 do
- monitor.setCursorPos(x1, y) monitor.write(" ")
- monitor.setCursorPos(x2, y) monitor.write(" ")
- end
- end
- local function drawProgressBar(x1, y, x2, percent, bg, fg)
- local barLen = x2 - x1 + 1
- local fill = math.floor(barLen * percent)
- monitor.setCursorPos(x1, y)
- monitor.setBackgroundColor(bg)
- monitor.write(string.rep(" ", barLen))
- monitor.setCursorPos(x1, y)
- monitor.setBackgroundColor(fg)
- monitor.write(string.rep(" ", fill))
- end
- local function getColorByPercent(p)
- if p > 0.75 then return colors.green
- elseif p > 0.5 then return colors.yellow
- elseif p > 0.25 then return colors.orange
- else return colors.red end
- end
- local function drawClock()
- local t = textutils.formatTime(os.time(), true)
- drawCenteredText(1, width, height, t, colors.lightGray)
- end
- local function updateHistories()
- local used = meBridge.getUsedItemStorage()
- local total = meBridge.getTotalItemStorage()
- table.insert(histories[2], used / total)
- local cpus = meBridge.getCraftingCPUs() or {}
- local busy = 0
- for _, c in ipairs(cpus) do if c.busy then busy = busy + 1 end end
- table.insert(histories[1], #cpus > 0 and busy / #cpus or 0)
- local power = meBridge.getEnergyStorage() or 0
- table.insert(histories[4], power / 1000000)
- for i = 1, 4 do if #histories[i] > MAX_HISTORY then table.remove(histories[i], 1) end end
- end
- local function drawHistograph(x1, y1, x2, y2, data, color)
- local w = x2 - x1 + 1
- local h = y2 - y1
- for i = 1, math.min(w, #data) do
- local val = data[#data - i + 1]
- local heightFill = math.floor(h * val)
- for j = 0, h - 1 do
- monitor.setCursorPos(x2 - i + 1, y2 - j)
- if j < heightFill then
- monitor.setBackgroundColor(color)
- else
- monitor.setBackgroundColor(colors.black)
- end
- monitor.write(" ")
- end
- end
- end
- local function drawEvents(x1, x2, startY)
- for i, event in ipairs(events) do
- if startY + i - 1 <= height - 1 then
- monitor.setCursorPos(x1, startY + i - 1)
- monitor.setTextColor(colors.gray)
- monitor.setBackgroundColor(colors.black)
- monitor.write(string.rep(" ", x2 - x1 + 1)) -- Clear line first
- monitor.setCursorPos(x1, startY + i - 1)
- monitor.write(string.sub(event, 1, x2 - x1 + 1))
- end
- end
- end
- local function drawStorage(x1, y1, x2, y2, isExpanded)
- local used = meBridge.getUsedItemStorage()
- local total = meBridge.getTotalItemStorage()
- local pct = used / total
- local bg = pct > 0.75 and colors.red or colors.black
- if not isExpanded then
- clearArea(x1, y1, x2, y2, bg)
- drawBorder(x1, y1, x2, y2, colors.white)
- end
- drawCenteredText(x1, x2, y1 + 1, "STORAGE", colors.white, bg)
- drawCenteredText(x1, x2, y1 + 3, (math.floor(pct * 1000)/10).."% Used", colors.white, bg)
- drawProgressBar(x1+2, y1+5, x2-2, pct, colors.blue, getColorByPercent(pct))
- if pct > 0.75 and blink then
- drawCenteredText(x1, x2, y2-2, "!!WARNING!!", colors.white, colors.red)
- logEvent("Low Free Storage")
- end
- end
- local function drawCrafting(x1, y1, x2, y2, isExpanded)
- local cpus = meBridge.getCraftingCPUs() or {}
- local count = #cpus
- local busy = 0
- for _, cpu in ipairs(cpus) do if cpu.busy then busy = busy + 1 end end
- local pct = count > 0 and (busy / count) or 0
- if not isExpanded then
- clearArea(x1, y1, x2, y2, colors.black)
- drawBorder(x1, y1, x2, y2, colors.white)
- end
- drawCenteredText(x1, x2, y1 + 1, "CRAFTING", colors.white)
- drawCenteredText(x1, x2, y1 + 3, "Busy: " .. busy .. "/" .. count, colors.white)
- drawProgressBar(x1+2, y1+5, x2-2, pct, colors.gray, colors.green)
- end
- local function drawPower(x1, y1, x2, y2, isExpanded)
- local usage = meBridge.getAvgPowerUsage() or 0
- local stored = meBridge.getEnergyStorage() or 0
- if not isExpanded then
- clearArea(x1, y1, x2, y2, colors.black)
- drawBorder(x1, y1, x2, y2, colors.white)
- end
- drawCenteredText(x1, x2, y1 + 1, "POWER", colors.white)
- drawCenteredText(x1, x2, y1 + 3, "Avg: "..math.floor(usage).." RF/t", colors.white)
- drawCenteredText(x1, x2, y1 + 4, "Stored: "..math.floor(stored), colors.white)
- if stored < 10000 then logEvent("Low Power: "..stored) end
- end
- local function drawWIP(x1, y1, x2, y2, isExpanded)
- if not isExpanded then
- clearArea(x1, y1, x2, y2, colors.black)
- drawBorder(x1, y1, x2, y2, colors.white)
- end
- drawCenteredText(x1, x2, y1 + math.floor((y2 - y1) / 2), "WIP", colors.gray)
- end
- local function drawAll()
- for i = 1, 4 do
- local q = quads[i]
- if i == 1 then drawCrafting(table.unpack(q))
- elseif i == 2 then drawStorage(table.unpack(q))
- elseif i == 3 then drawWIP(table.unpack(q))
- elseif i == 4 then drawPower(table.unpack(q)) end
- end
- drawClock()
- end
- local function drawExpanded(index)
- clearArea(1, 1, width, height, colors.black)
- -- Draw the main content first
- local h = histories[index]
- if index == 1 then drawCrafting(1, 3, width, height, true)
- elseif index == 2 then drawStorage(1, 3, width, height, true)
- elseif index == 3 then drawWIP(1, 3, width, height, true)
- elseif index == 4 then drawPower(1, 3, width, height, true) end
- -- Draw histograph and events
- drawHistograph(2, height/2 - 6, width - 2, height/2 + 2, h, colors.lime)
- drawEvents(2, width - 2, height/2 + 3)
- -- Draw back button LAST so it doesn't get overwritten
- monitor.setCursorPos(width - 8, 1)
- monitor.setTextColor(colors.black)
- monitor.setBackgroundColor(colors.white)
- monitor.write("[ BACK ]")
- drawClock()
- end
- local function handleClick(x, y)
- if expanded then
- if x >= width - 8 and x <= width and y == 1 then
- expanded = nil
- logEvent("Returned to main view")
- end
- else
- for i, q in ipairs(quads) do
- if x >= q[1] and x <= q[3] and y >= q[2] and y <= q[4] then
- expanded = i
- local names = {"Crafting", "Storage", "WIP", "Power"}
- logEvent("Opened " .. names[i] .. " view")
- return
- end
- end
- end
- end
- -- Coroutine for display updates
- local function displayCoroutine()
- while true do
- local currentTime = os.clock()
- -- Update blink state
- if currentTime - lastBlink >= 0.5 then
- blink = not blink
- lastBlink = currentTime
- end
- -- Update data and display every second
- if currentTime - lastUpdate >= 1.0 then
- updateHistories()
- if expanded then
- drawExpanded(expanded)
- else
- drawAll()
- end
- lastUpdate = currentTime
- end
- coroutine.yield()
- end
- end
- -- Coroutine for event handling
- local function eventCoroutine()
- while true do
- local event, side, x, y = os.pullEvent()
- if event == "monitor_touch" then
- handleClick(x, y)
- -- Force immediate redraw after click
- if expanded then
- drawExpanded(expanded)
- else
- drawAll()
- end
- elseif event == "terminate" then
- return false -- Signal to exit
- end
- coroutine.yield()
- end
- end
- -- Main execution with coroutines
- local displayCo = coroutine.create(displayCoroutine)
- local eventCo = coroutine.create(eventCoroutine)
- -- Initial draw
- updateHistories()
- drawAll()
- -- Main loop
- while true do
- -- Resume display coroutine
- local ok, result = coroutine.resume(displayCo)
- if not ok then
- print("Display error: " .. result)
- break
- end
- -- Resume event coroutine
- ok, result = coroutine.resume(eventCo)
- if not ok then
- print("Event error: " .. result)
- break
- elseif result == false then
- break -- Terminate signal
- end
- -- Small delay to prevent excessive CPU usage
- sleep(0.05)
- end
Advertisement
Add Comment
Please, Sign In to add comment