April_The_Sergal

AE2 Display

Jul 21st, 2025 (edited)
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.11 KB | None | 0 0
  1. -- ME System Monitor for CC:Tweaked (Enhanced with Clock + Histograph + Events + Coroutines)
  2.  
  3. local monitor = peripheral.find("monitor")
  4. local meBridge = peripheral.wrap("bottom")
  5.  
  6. if not monitor then error("Monitor not found") end
  7. if not meBridge then error("ME Bridge not found") end
  8.  
  9. monitor.setTextScale(0.5)
  10. local width, height = monitor.getSize()
  11.  
  12. local expanded = nil
  13. local currentCPU = 1
  14. local blink = true
  15. local lastBlink = 0
  16. local lastUpdate = 0
  17.  
  18. local quads = {
  19.     {1, 1, math.floor(width/2), math.floor(height/2)},
  20.     {math.floor(width/2)+1, 1, width, math.floor(height/2)},
  21.     {1, math.floor(height/2)+1, math.floor(width/2), height},
  22.     {math.floor(width/2)+1, math.floor(height/2)+1, width, height}
  23. }
  24.  
  25. -- Histograph and events
  26. local histories = {{}, {}, {}, {}}
  27. local events = {}
  28. local MAX_HISTORY = width - 4
  29. local MAX_EVENTS = 5
  30.  
  31. local function logEvent(msg)
  32.     table.insert(events, 1, os.date("%H:%M:%S") .. " - " .. msg)
  33.     if #events > MAX_EVENTS then table.remove(events) end
  34. end
  35.  
  36. local function clearArea(x1, y1, x2, y2, color)
  37.     monitor.setBackgroundColor(color or colors.black)
  38.     for y = y1, y2 do
  39.         monitor.setCursorPos(x1, y)
  40.         monitor.write(string.rep(" ", x2 - x1 + 1))
  41.     end
  42. end
  43.  
  44. local function drawCenteredText(x1, x2, y, text, textColor, bg)
  45.     monitor.setTextColor(textColor or colors.white)
  46.     monitor.setBackgroundColor(bg or colors.black)
  47.     local cx = math.floor((x1 + x2 - #text) / 2)
  48.     monitor.setCursorPos(cx, y)
  49.     monitor.write(text)
  50. end
  51.  
  52. local function drawBorder(x1, y1, x2, y2, color)
  53.     monitor.setBackgroundColor(color)
  54.     for x = x1, x2 do
  55.         monitor.setCursorPos(x, y1) monitor.write(" ")
  56.         monitor.setCursorPos(x, y2) monitor.write(" ")
  57.     end
  58.     for y = y1 + 1, y2 - 1 do
  59.         monitor.setCursorPos(x1, y) monitor.write(" ")
  60.         monitor.setCursorPos(x2, y) monitor.write(" ")
  61.     end
  62. end
  63.  
  64. local function drawProgressBar(x1, y, x2, percent, bg, fg)
  65.     local barLen = x2 - x1 + 1
  66.     local fill = math.floor(barLen * percent)
  67.     monitor.setCursorPos(x1, y)
  68.     monitor.setBackgroundColor(bg)
  69.     monitor.write(string.rep(" ", barLen))
  70.     monitor.setCursorPos(x1, y)
  71.     monitor.setBackgroundColor(fg)
  72.     monitor.write(string.rep(" ", fill))
  73. end
  74.  
  75. local function getColorByPercent(p)
  76.     if p > 0.75 then return colors.green
  77.     elseif p > 0.5 then return colors.yellow
  78.     elseif p > 0.25 then return colors.orange
  79.     else return colors.red end
  80. end
  81.  
  82. local function drawClock()
  83.     local t = textutils.formatTime(os.time(), true)
  84.     drawCenteredText(1, width, height, t, colors.lightGray)
  85. end
  86.  
  87. local function updateHistories()
  88.     local used = meBridge.getUsedItemStorage()
  89.     local total = meBridge.getTotalItemStorage()
  90.     table.insert(histories[2], used / total)
  91.  
  92.     local cpus = meBridge.getCraftingCPUs() or {}
  93.     local busy = 0
  94.     for _, c in ipairs(cpus) do if c.busy then busy = busy + 1 end end
  95.     table.insert(histories[1], #cpus > 0 and busy / #cpus or 0)
  96.  
  97.     local power = meBridge.getEnergyStorage() or 0
  98.     table.insert(histories[4], power / 1000000)
  99.  
  100.     for i = 1, 4 do if #histories[i] > MAX_HISTORY then table.remove(histories[i], 1) end end
  101. end
  102.  
  103. local function drawHistograph(x1, y1, x2, y2, data, color)
  104.     local w = x2 - x1 + 1
  105.     local h = y2 - y1
  106.     for i = 1, math.min(w, #data) do
  107.         local val = data[#data - i + 1]
  108.         local heightFill = math.floor(h * val)
  109.         for j = 0, h - 1 do
  110.             monitor.setCursorPos(x2 - i + 1, y2 - j)
  111.             if j < heightFill then
  112.                 monitor.setBackgroundColor(color)
  113.             else
  114.                 monitor.setBackgroundColor(colors.black)
  115.             end
  116.             monitor.write(" ")
  117.         end
  118.     end
  119. end
  120.  
  121. local function drawEvents(x1, x2, startY)
  122.     for i, event in ipairs(events) do
  123.         if startY + i - 1 <= height - 1 then
  124.             monitor.setCursorPos(x1, startY + i - 1)
  125.             monitor.setTextColor(colors.gray)
  126.             monitor.setBackgroundColor(colors.black)
  127.             monitor.write(string.rep(" ", x2 - x1 + 1)) -- Clear line first
  128.             monitor.setCursorPos(x1, startY + i - 1)
  129.             monitor.write(string.sub(event, 1, x2 - x1 + 1))
  130.         end
  131.     end
  132. end
  133.  
  134. local function drawStorage(x1, y1, x2, y2, isExpanded)
  135.     local used = meBridge.getUsedItemStorage()
  136.     local total = meBridge.getTotalItemStorage()
  137.     local pct = used / total
  138.     local bg = pct > 0.75 and colors.red or colors.black
  139.  
  140.     if not isExpanded then
  141.         clearArea(x1, y1, x2, y2, bg)
  142.         drawBorder(x1, y1, x2, y2, colors.white)
  143.     end
  144.    
  145.     drawCenteredText(x1, x2, y1 + 1, "STORAGE", colors.white, bg)
  146.     drawCenteredText(x1, x2, y1 + 3, (math.floor(pct * 1000)/10).."% Used", colors.white, bg)
  147.     drawProgressBar(x1+2, y1+5, x2-2, pct, colors.blue, getColorByPercent(pct))
  148.  
  149.     if pct > 0.75 and blink then
  150.         drawCenteredText(x1, x2, y2-2, "!!WARNING!!", colors.white, colors.red)
  151.         logEvent("Low Free Storage")
  152.     end
  153. end
  154.  
  155. local function drawCrafting(x1, y1, x2, y2, isExpanded)
  156.     local cpus = meBridge.getCraftingCPUs() or {}
  157.     local count = #cpus
  158.     local busy = 0
  159.     for _, cpu in ipairs(cpus) do if cpu.busy then busy = busy + 1 end end
  160.     local pct = count > 0 and (busy / count) or 0
  161.  
  162.     if not isExpanded then
  163.         clearArea(x1, y1, x2, y2, colors.black)
  164.         drawBorder(x1, y1, x2, y2, colors.white)
  165.     end
  166.    
  167.     drawCenteredText(x1, x2, y1 + 1, "CRAFTING", colors.white)
  168.     drawCenteredText(x1, x2, y1 + 3, "Busy: " .. busy .. "/" .. count, colors.white)
  169.     drawProgressBar(x1+2, y1+5, x2-2, pct, colors.gray, colors.green)
  170. end
  171.  
  172. local function drawPower(x1, y1, x2, y2, isExpanded)
  173.     local usage = meBridge.getAvgPowerUsage() or 0
  174.     local stored = meBridge.getEnergyStorage() or 0
  175.  
  176.     if not isExpanded then
  177.         clearArea(x1, y1, x2, y2, colors.black)
  178.         drawBorder(x1, y1, x2, y2, colors.white)
  179.     end
  180.    
  181.     drawCenteredText(x1, x2, y1 + 1, "POWER", colors.white)
  182.     drawCenteredText(x1, x2, y1 + 3, "Avg: "..math.floor(usage).." RF/t", colors.white)
  183.     drawCenteredText(x1, x2, y1 + 4, "Stored: "..math.floor(stored), colors.white)
  184.     if stored < 10000 then logEvent("Low Power: "..stored) end
  185. end
  186.  
  187. local function drawWIP(x1, y1, x2, y2, isExpanded)
  188.     if not isExpanded then
  189.         clearArea(x1, y1, x2, y2, colors.black)
  190.         drawBorder(x1, y1, x2, y2, colors.white)
  191.     end
  192.     drawCenteredText(x1, x2, y1 + math.floor((y2 - y1) / 2), "WIP", colors.gray)
  193. end
  194.  
  195. local function drawAll()
  196.     for i = 1, 4 do
  197.         local q = quads[i]
  198.         if i == 1 then drawCrafting(table.unpack(q))
  199.         elseif i == 2 then drawStorage(table.unpack(q))
  200.         elseif i == 3 then drawWIP(table.unpack(q))
  201.         elseif i == 4 then drawPower(table.unpack(q)) end
  202.     end
  203.     drawClock()
  204. end
  205.  
  206. local function drawExpanded(index)
  207.     clearArea(1, 1, width, height, colors.black)
  208.    
  209.     -- Draw the main content first
  210.     local h = histories[index]
  211.     if index == 1 then drawCrafting(1, 3, width, height, true)
  212.     elseif index == 2 then drawStorage(1, 3, width, height, true)
  213.     elseif index == 3 then drawWIP(1, 3, width, height, true)
  214.     elseif index == 4 then drawPower(1, 3, width, height, true) end
  215.    
  216.     -- Draw histograph and events
  217.     drawHistograph(2, height/2 - 6, width - 2, height/2 + 2, h, colors.lime)
  218.     drawEvents(2, width - 2, height/2 + 3)
  219.    
  220.     -- Draw back button LAST so it doesn't get overwritten
  221.     monitor.setCursorPos(width - 8, 1)
  222.     monitor.setTextColor(colors.black)
  223.     monitor.setBackgroundColor(colors.white)
  224.     monitor.write("[ BACK ]")
  225.    
  226.     drawClock()
  227. end
  228.  
  229. local function handleClick(x, y)
  230.     if expanded then
  231.         if x >= width - 8 and x <= width and y == 1 then
  232.             expanded = nil
  233.             logEvent("Returned to main view")
  234.         end
  235.     else
  236.         for i, q in ipairs(quads) do
  237.             if x >= q[1] and x <= q[3] and y >= q[2] and y <= q[4] then
  238.                 expanded = i
  239.                 local names = {"Crafting", "Storage", "WIP", "Power"}
  240.                 logEvent("Opened " .. names[i] .. " view")
  241.                 return
  242.             end
  243.         end
  244.     end
  245. end
  246.  
  247. -- Coroutine for display updates
  248. local function displayCoroutine()
  249.     while true do
  250.         local currentTime = os.clock()
  251.        
  252.         -- Update blink state
  253.         if currentTime - lastBlink >= 0.5 then
  254.             blink = not blink
  255.             lastBlink = currentTime
  256.         end
  257.        
  258.         -- Update data and display every second
  259.         if currentTime - lastUpdate >= 1.0 then
  260.             updateHistories()
  261.            
  262.             if expanded then
  263.                 drawExpanded(expanded)
  264.             else
  265.                 drawAll()
  266.             end
  267.            
  268.             lastUpdate = currentTime
  269.         end
  270.        
  271.         coroutine.yield()
  272.     end
  273. end
  274.  
  275. -- Coroutine for event handling
  276. local function eventCoroutine()
  277.     while true do
  278.         local event, side, x, y = os.pullEvent()
  279.        
  280.         if event == "monitor_touch" then
  281.             handleClick(x, y)
  282.             -- Force immediate redraw after click
  283.             if expanded then
  284.                 drawExpanded(expanded)
  285.             else
  286.                 drawAll()
  287.             end
  288.         elseif event == "terminate" then
  289.             return false -- Signal to exit
  290.         end
  291.        
  292.         coroutine.yield()
  293.     end
  294. end
  295.  
  296. -- Main execution with coroutines
  297. local displayCo = coroutine.create(displayCoroutine)
  298. local eventCo = coroutine.create(eventCoroutine)
  299.  
  300. -- Initial draw
  301. updateHistories()
  302. drawAll()
  303.  
  304. -- Main loop
  305. while true do
  306.     -- Resume display coroutine
  307.     local ok, result = coroutine.resume(displayCo)
  308.     if not ok then
  309.         print("Display error: " .. result)
  310.         break
  311.     end
  312.    
  313.     -- Resume event coroutine
  314.     ok, result = coroutine.resume(eventCo)
  315.     if not ok then
  316.         print("Event error: " .. result)
  317.         break
  318.     elseif result == false then
  319.         break -- Terminate signal
  320.     end
  321.    
  322.     -- Small delay to prevent excessive CPU usage
  323.     sleep(0.05)
  324. end
Advertisement
Add Comment
Please, Sign In to add comment