Advertisement
Guest User

Untitled

a guest
Aug 24th, 2016
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.43 KB | None | 0 0
  1. -- RF Control Center (RFCC) v0.3
  2. -- by dlord
  3.  
  4.  
  5. -- Main configuration
  6. local tArgs = {...}
  7. local CONFIG_FILE = "power_conf"
  8.  
  9. local CONFIG_TEMPLATE = [[-- adjust these configuration options as necessary.
  10. -- delay for checking all capacitors
  11. TICK_DELAY = ${tickDelay}
  12.  
  13. -- threshold in percentages
  14. GREEN_ZONE = ${greenZone}
  15. YELLOW_ZONE = ${yellowZone}
  16.  
  17. NORMAL_POWER_THRESHOLD = ${nomalPowerThreshold}
  18. LOW_POWER_THRESHOLD = ${lowPowerThreshold}
  19.  
  20. -- configures what side to emit when low power
  21. -- a valid side is required.
  22. SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = "${sideForRedstone}"
  23.  
  24. -- Active monitors on startup
  25. MONITORS_ACTIVE = ${monitorsActive}
  26. ]]
  27.  
  28. local MONITORS_ACTIVE = {}
  29.  
  30. do
  31. if #tArgs > 0 and tArgs[1] == "update" then
  32. print("Updating RFCC...")
  33. local updateFile = "/rfcc_update"
  34. local pastebinKey = "TfeHE7Wy"
  35. shell.run("pastebin", "get", pastebinKey, updateFile)
  36.  
  37. if fs.exists(updateFile) then
  38. local programPath = shell.getRunningProgram()
  39. fs.delete(programPath)
  40. fs.move(updateFile, programPath)
  41. print("Success!")
  42. return
  43. else
  44. print("Unable to retrieve update from pastebin.")
  45. print("Check your connection, and try again.")
  46. error()
  47. end
  48. end
  49. end
  50.  
  51. local function interpolate(s, params)
  52. return s:gsub('($%b{})', function(w) return params[w:sub(3, -2)] or w end)
  53. end
  54.  
  55. local function saveSettings()
  56. local h = fs.open("/"..CONFIG_FILE, "w")
  57.  
  58. local settings = {
  59. tickDelay = TICK_DELAY or 100,
  60. greenZone = GREEN_ZONE or 70,
  61. yellowZone = YELLOW_ZONE or 30,
  62. nomalPowerThreshold = NORMAL_POWER_THRESHOLD or 90,
  63. lowPowerThreshold = LOW_POWER_THRESHOLD or 10,
  64. sideForRedstone = SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER or "bottom",
  65. monitorsActive = textutils.serialize(MONITORS_ACTIVE)
  66. }
  67.  
  68. h.write(interpolate(CONFIG_TEMPLATE, settings))
  69. h.close()
  70. end
  71.  
  72.  
  73. if fs.exists(CONFIG_FILE) == false then
  74. print("I can't find my configuration file.")
  75. print("Generating one for you.")
  76.  
  77. saveSettings()
  78.  
  79. print("")
  80. print("Configuration file is located at /"..CONFIG_FILE)
  81. print("You may edit this file to change my default settings.")
  82. print("Once satisfied, run me again.")
  83. return
  84. else
  85. os.unloadAPI(CONFIG_FILE)
  86.  
  87. if os.loadAPI("/"..CONFIG_FILE) == false then
  88. error("Could not load the config file!")
  89. end
  90.  
  91. CONFIG = nil
  92. for k, v in pairs(_G) do
  93. if k == CONFIG_FILE then
  94. CONFIG = v
  95. break
  96. end
  97. end
  98.  
  99. if CONFIG == nil then
  100. print("I could not find the necessary config.")
  101. print("You probably screwed something up.")
  102. error()
  103. end
  104. end
  105.  
  106. term.setCursorPos(1, 1)
  107. term.clear()
  108. print("Starting RF Control Center...")
  109. sleep(2)
  110.  
  111. -- Constants
  112. local GET_ENERGY_STORED_FUNCTION="getEnergyStored"
  113. local GET_MAX_ENERGY_STORED_FUNCTION="getMaxEnergyStored"
  114.  
  115. local TICK_DELAY = CONFIG.TICK_DELAY
  116. local PAUSE_TIME_IN_SECONDS = TICK_DELAY / 20
  117.  
  118. -- threshold in percentages
  119. local GREEN_ZONE = CONFIG.GREEN_ZONE
  120. local YELLOW_ZONE = CONFIG.YELLOW_ZONE
  121.  
  122. local NORMAL_POWER_THRESHOLD = CONFIG.NORMAL_POWER_THRESHOLD
  123. local LOW_POWER_THRESHOLD = CONFIG.LOW_POWER_THRESHOLD
  124.  
  125. -- configures what side to emit when low power
  126. local SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = CONFIG.SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER
  127.  
  128. MONITORS_ACTIVE = CONFIG.MONITORS_ACTIVE
  129.  
  130. -- state variables
  131. local clickableLines = {}
  132. local clickableOutputMonitors = {}
  133. local monitors = {}
  134. local capacitors = {}
  135. local dashboardButtons = {}
  136. local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
  137.  
  138. -- Capacitor basic functions
  139. do
  140. capacitors.add = function(params)
  141. table.insert(capacitors, params)
  142. end
  143.  
  144. capacitors.get = function(name)
  145. for i, v in ipairs(capacitors) do
  146. if name == v.name then
  147. return v
  148. end
  149. end
  150.  
  151. return nil
  152. end
  153.  
  154. capacitors.remove = function(name)
  155. local found = nil
  156. for i, v in ipairs(capacitors) do
  157. if name == v.name then
  158. found = i
  159. break
  160. end
  161. end
  162.  
  163. if found then
  164. table.remove(capacitors, found)
  165. end
  166. end
  167.  
  168. capacitors.clear = function()
  169. for i, v in ipairs(capacitors) do
  170. capacitors[i] = nil
  171. end
  172. end
  173. end
  174.  
  175.  
  176. -- Special Windows
  177. local nativeDisplayTabs = {}
  178. local nativeMonitorTabWindow
  179. local consoleWindow
  180. local monitorSelectionWindow
  181.  
  182. do
  183. local nativeTerm = term.native()
  184. local width, height = term.getSize()
  185. local x, y = 1, 2
  186. local newWidth, newHeight = width, height - 1
  187.  
  188. nativeTerm.setCursorPos(x, y)
  189.  
  190. nativeMonitorTabWindow = window.create(nativeTerm, 1, 1, width, 1, false)
  191.  
  192. consoleWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
  193. consoleWindow.active = true
  194.  
  195. monitorSelectionWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
  196. monitorSelectionWindow.active = true
  197. end
  198.  
  199. -- TODO: break up this humongous script into smaller chunks that can be loaded
  200. -- via os.loadAPI().
  201.  
  202.  
  203. -- basic functions
  204. local function tableSize(targetTable)
  205. local i = 0
  206. for k, v in pairs(targetTable) do
  207. i = i + 1
  208. end
  209.  
  210. return i
  211. end
  212.  
  213. local function padRight(text, width, padCharacter)
  214. if width == nil then
  215. width = term.getSize()
  216. end
  217.  
  218. padCount = width - string.len(text)
  219.  
  220. if padCharacter == nil then
  221. padCharacter = " "
  222. end
  223.  
  224. if padCount > 0 then
  225. return text..string.rep(padCharacter, padCount)
  226. else
  227. return text
  228. end
  229. end
  230.  
  231. local function padLeft(text, width, padCharacter)
  232. if width == nil then
  233. width = term.getSize()
  234. end
  235.  
  236. padCount = width - string.len(text)
  237.  
  238. if padCharacter == nil then
  239. padCharacter = " "
  240. end
  241.  
  242. if padCount > 0 then
  243. return string.rep(padCharacter, padCount)..text
  244. else
  245. return text
  246. end
  247. end
  248.  
  249. local function printZoneText(percent, callback)
  250. if percent >= GREEN_ZONE then
  251. term.setTextColor(colors.green)
  252. elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
  253. term.setTextColor(colors.yellow)
  254. else
  255. term.setTextColor(colors.red)
  256. end
  257.  
  258. callback()
  259.  
  260. term.setTextColor(colors.white)
  261. end
  262.  
  263. local function resetRedstoneState()
  264. for k,v in pairs(rs.getSides()) do
  265. rs.setOutput(v, false)
  266. end
  267. end
  268. -- basic functions
  269.  
  270.  
  271. -- line drawing API
  272. local function drawVerticalLine(targetWindow, x, y, height)
  273. targetWindow.setCursorPos(x, y)
  274.  
  275. targetWindow.setBackgroundColor(colors.blue)
  276. for i = 1, height do
  277. targetWindow.write(" ")
  278. targetWindow.setCursorPos(x, i)
  279. end
  280. targetWindow.setBackgroundColor(colors.black)
  281. end
  282.  
  283. local function drawHorizontalLine(targetWindow, x, y, width)
  284. targetWindow.setCursorPos(x, y)
  285. targetWindow.setBackgroundColor(colors.blue)
  286. targetWindow.write(string.rep(" ", width))
  287. targetWindow.setBackgroundColor(colors.black)
  288. end
  289. -- line drawing API
  290.  
  291.  
  292. -- window management
  293. local console = {
  294. log = function(message)
  295. local currentTerm = term.current()
  296. term.redirect(consoleWindow)
  297.  
  298. print(message)
  299.  
  300. term.redirect(currentTerm)
  301. end
  302. }
  303.  
  304. local function showWindows(...)
  305. for i, v in ipairs(arg) do
  306. if v.active == true then
  307. v.setVisible(true)
  308. else
  309. v.setVisible(false)
  310. end
  311. end
  312. end
  313.  
  314. local function hideWindows(...)
  315. for i, v in ipairs(arg) do
  316. v.setVisible(false)
  317. end
  318. end
  319.  
  320. local function getCursorPositionRelativeToParent(currentWindow)
  321. -- determine offset of current window from parent
  322. local x, y = currentWindow.getPosition()
  323. local xOffset, yOffset = x - 1, y - 1
  324.  
  325. local cursorX, cursorY = currentWindow.getCursorPos()
  326. return cursorX + xOffset, cursorY + yOffset
  327. end
  328.  
  329. local function createInformationWindow(parentWindow)
  330. local width, height = parentWindow.getSize()
  331.  
  332. local widthOffset = 2
  333. local heightOffset = 2
  334.  
  335. local windowWidth = width - (widthOffset * 2)
  336. local windowHeight = height - (heightOffset * 2)
  337.  
  338. local informationWindow = window.create(parentWindow, 1 + widthOffset, 1 + heightOffset, windowWidth, windowHeight, false)
  339. informationWindow.active = false
  340.  
  341. drawHorizontalLine(informationWindow, 1, 1, windowWidth)
  342. drawHorizontalLine(informationWindow, 1, windowHeight, windowWidth)
  343.  
  344. drawVerticalLine(informationWindow, 1, 1, windowHeight)
  345. drawVerticalLine(informationWindow, windowWidth, 1, windowHeight)
  346.  
  347. return informationWindow
  348. end
  349.  
  350. local function createSummaryWindow(parentWindow, x, y)
  351. local width, height = parentWindow.getSize()
  352.  
  353. -- we make use of the parent window's cursor position to make it more convenient.
  354. local x, y = parentWindow.getCursorPos()
  355. local newHeight = height - (y - 1)
  356.  
  357. local summaryWindow = window.create(parentWindow, x, y, width, newHeight, false)
  358. summaryWindow.active = false
  359.  
  360. return summaryWindow
  361. end
  362.  
  363. local function printToWindow(targetWindow, widthOffset, text)
  364. local x, y = targetWindow.getCursorPos()
  365. local width, height = targetWindow.getSize()
  366. local maxTextSize = width - (widthOffset * 2)
  367.  
  368. targetWindow.write(text:sub(1, maxTextSize))
  369. targetWindow.setCursorPos(x, y+1)
  370. end
  371.  
  372. local function createDashboardWindows(parentWindow)
  373. -- order is important here!
  374. local summaryWindow = createSummaryWindow(parentWindow)
  375. summaryWindow.active = true
  376. local informationWindow = createInformationWindow(parentWindow)
  377. informationWindow.active = false
  378.  
  379. local windows = {
  380. [1] = summaryWindow,
  381. [2] = informationWindow,
  382.  
  383. getSummaryWindow = function()
  384. return summaryWindow
  385. end,
  386.  
  387. getInformationWindow = function()
  388. return informationWindow
  389. end
  390. }
  391.  
  392. return windows
  393. end
  394.  
  395. local function initializeNativeDisplayTabs()
  396. local nativeTerm = term.native()
  397. nativeTerm.setCursorPos(1, 2)
  398.  
  399. local dashboardWindows = createDashboardWindows(nativeTerm)
  400.  
  401. table.insert(nativeDisplayTabs, {
  402. tab = {
  403. label = "Dashboard",
  404. event = "dashboard_clicked",
  405. active = true,
  406. startX = 0,
  407. startY = 0
  408. },
  409.  
  410. windows = dashboardWindows
  411. })
  412. table.insert(nativeDisplayTabs, {
  413. tab = {
  414. label = "Monitors",
  415. event = "monitors_clicked",
  416. startX = 0,
  417. startY = 0
  418. },
  419.  
  420. windows = { monitorSelectionWindow }
  421. })
  422. table.insert(nativeDisplayTabs, {
  423. tab = {
  424. label = "Console",
  425. event = "console_clicked",
  426. startX = 0,
  427. startY = 0
  428. },
  429.  
  430. windows = { consoleWindow }
  431. })
  432.  
  433. nativeDisplayTabs.getSelectedTab = function(x, y)
  434. if x == nil or y == nil then
  435. return nil
  436. end
  437.  
  438. for i, v in ipairs(nativeDisplayTabs) do
  439. local tab = v.tab
  440. local withinX = x >= tab.startX and x <= tab.endX
  441. local withinY = y >= tab.startY and y <= tab.endY
  442.  
  443. if withinX and withinY then
  444. return i
  445. end
  446. end
  447.  
  448. return nil
  449. end
  450.  
  451. nativeDisplayTabs.setSelectedTab = function(selected)
  452. for i, v in ipairs(nativeDisplayTabs) do
  453. if i == selected then
  454. v.tab.active = true
  455. else
  456. v.tab.active = false
  457. end
  458. end
  459. end
  460.  
  461. nativeDisplayTabs.getActiveTab = function()
  462. for i, v in ipairs(nativeDisplayTabs) do
  463. if v.tab.active == true then
  464. return i
  465. end
  466. end
  467. end
  468.  
  469. nativeDisplayTabs.getDashboardWindows = function()
  470. return dashboardWindows
  471. end
  472. end
  473.  
  474. -- window management
  475.  
  476.  
  477. -- capacitor management
  478. local function addCapacitors(...)
  479. local peripheralList = arg
  480.  
  481. if #peripheralList == 0 then
  482. peripheralList = peripheral.getNames()
  483. capacitors.clear()
  484. end
  485.  
  486. for i, p in ipairs(peripheralList) do
  487. local currentPeripheral = peripheral.wrap(p)
  488.  
  489. if currentPeripheral[GET_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_ENERGY_STORED_FUNCTION]("north") ~= nil then
  490. console.log("Adding new capacitor: "..p)
  491. capacitors.add({
  492. name = p,
  493. peripheral = currentPeripheral,
  494. lastReading = 0,
  495. flowRate = 0,
  496. percent = 0
  497. })
  498. end
  499. end
  500. end
  501.  
  502. local function removeCapacitors(...)
  503. for i, k in ipairs(arg) do
  504. capacitors.remove(k)
  505. end
  506. end
  507.  
  508. local function getReading()
  509. local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
  510.  
  511. for i, v in ipairs(capacitors) do
  512. local currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION]("north") or 0
  513. local capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north") or 0
  514.  
  515. if currentReading ~= nil then
  516. v.flowRate = (currentReading - v.lastReading) / TICK_DELAY
  517. v.lastReading = currentReading
  518.  
  519. if capacity == 0 then
  520. v.percent = 0
  521. else
  522. v.percent = math.floor((currentReading / capacity) * 100)
  523. end
  524.  
  525. totalEnergyAvailable = totalEnergyAvailable + v.lastReading
  526. totalFlowRate = totalFlowRate + v.flowRate
  527. end
  528.  
  529. totalCapacity = totalCapacity + capacity
  530. end
  531.  
  532. local sortByLastReading = function(a, b)
  533. return a.percent > b.percent
  534. end
  535.  
  536. table.sort(capacitors, sortByLastReading)
  537.  
  538. return totalEnergyAvailable, totalCapacity, totalFlowRate
  539. end
  540.  
  541. local function emitRedstoneSignalOnLowPower(percent)
  542. if percent < LOW_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == false then
  543. console.log("Low power threshold reached.")
  544. rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, true)
  545. elseif percent >= NORMAL_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == true then
  546. console.log("Back to normal power levels.")
  547. rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, false)
  548. end
  549. end
  550. -- capacitor management
  551.  
  552.  
  553. -- monitor management
  554. local function addMonitors(...)
  555. local monitorList = arg
  556.  
  557. if #monitorList == 0 then
  558. monitorList = peripheral.getNames()
  559. monitors = {}
  560. end
  561.  
  562. for i, m in ipairs(monitorList) do
  563. local currentPeripheral = peripheral.wrap(m)
  564.  
  565. if "monitor" == peripheral.getType(m) and currentPeripheral.isColour() == true then
  566. console.log("Adding new monitor: "..m)
  567. currentPeripheral.setCursorPos(1, 1)
  568. monitors[m] = {
  569. peripheral = currentPeripheral,
  570. windows = createDashboardWindows(currentPeripheral),
  571. active = false
  572. }
  573. end
  574. end
  575. end
  576.  
  577. local function removeMonitors(...)
  578. local activeMonitorsCount = tableSize(MONITORS_ACTIVE)
  579.  
  580. for i, k in ipairs(arg) do
  581. monitors[k] = nil
  582. dashboardButtons[k] = nil
  583. MONITORS_ACTIVE[k] = nil
  584. end
  585.  
  586. if activeMonitorsCount ~= tableSize(MONITORS_ACTIVE) then
  587. saveSettings()
  588. end
  589. end
  590. -- monitor management
  591.  
  592.  
  593. -- hotplug system
  594. local function doWhileMonitorSuspended(callback)
  595. os.queueEvent("pause_monitor")
  596. callback()
  597. os.queueEvent("resume_monitor")
  598. end
  599.  
  600. local function hotplugPeripherals()
  601. while true do
  602. local event, name = os.pullEvent()
  603. local callback = nil
  604.  
  605. if event == "peripheral" then
  606. console.log("Detected new peripheral: "..name)
  607.  
  608. callback = function()
  609. addMonitors(name)
  610. addCapacitors(name)
  611. end
  612. elseif event == "peripheral_detach" then
  613. console.log("Peripheral removed: "..name)
  614.  
  615. callback = function()
  616. removeMonitors(name)
  617. removeCapacitors(name)
  618. end
  619. elseif event == "monitor_resize" then
  620. console.log("Monitor resized: "..name)
  621.  
  622. callback = function()
  623. monitors[name].peripheral.setCursorPos(1, 1)
  624. monitors[name].windows = createDashboardWindows(monitors[name].peripheral)
  625. dashboardButtons[name] = nil
  626.  
  627. if monitors[name].active == true then
  628. showWindows(unpack(monitors[name].windows))
  629. end
  630. end
  631. end
  632.  
  633. if callback ~= nil then
  634. doWhileMonitorSuspended(callback)
  635. end
  636. end
  637. end
  638. -- hotplug system
  639.  
  640.  
  641. -- information window for the capacitors
  642. local function addClickableLine(monitorName, key, currentY)
  643. clickableLines[monitorName][key] = {
  644. line = currentY
  645. }
  646. end
  647.  
  648. local function toggleInformationWindow(summaryWindow, informationWindow, capacitorName)
  649. if capacitorName == nil then
  650. summaryWindow.active = true
  651. informationWindow.active = false
  652. else
  653. summaryWindow.active = not summaryWindow.active
  654. informationWindow.active = not informationWindow.active
  655. end
  656.  
  657. local capacitor = capacitors.get(capacitorName)
  658.  
  659. if informationWindow.active == true then
  660. widthOffset = 3
  661. heightOffset = 3
  662.  
  663. informationWindow.setCursorPos(widthOffset, heightOffset)
  664. local width, height = informationWindow.getSize()
  665. local labelWidth = width - (widthOffset * 2)
  666. local capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north")
  667.  
  668. printToWindow(informationWindow, widthOffset, "Capacitor name:")
  669. printToWindow(informationWindow, widthOffset, padRight(" "..capacitorName, labelWidth))
  670. printToWindow(informationWindow, widthOffset, "Capacitor type:")
  671. printToWindow(informationWindow, widthOffset, padRight(" "..peripheral.getType(capacitorName), labelWidth))
  672. printToWindow(informationWindow, widthOffset, "Capacity:")
  673. printToWindow(informationWindow, widthOffset, padRight(" "..capacity.." RF", labelWidth))
  674. printToWindow(informationWindow, widthOffset, "Available:")
  675. printToWindow(informationWindow, widthOffset, padRight(" "..capacitor.lastReading.." RF", labelWidth))
  676.  
  677. local closeLabel = " Click anywhere to close "
  678.  
  679. local x = math.floor(((width - string.len(closeLabel)) / 2 ) + 0.5)
  680.  
  681. informationWindow.setCursorPos(x, height-2)
  682.  
  683. informationWindow.setBackgroundColor(colors.red)
  684. informationWindow.write(closeLabel)
  685. informationWindow.setBackgroundColor(colors.black)
  686. end
  687.  
  688. showWindows(summaryWindow, informationWindow)
  689. end
  690.  
  691. local function checkForSelectableLine(monitorName, x, y)
  692. if clickableLines[monitorName] == nil then
  693. return nil
  694. end
  695.  
  696. for k,v in pairs(clickableLines[monitorName]) do
  697. if y == v.line then
  698. return k
  699. end
  700. end
  701.  
  702. return nil
  703. end
  704.  
  705. local function getSelectedDashboardButton(monitorName, x, y)
  706. if x == nil or y == nil then
  707. return nil
  708. end
  709.  
  710. local v = dashboardButtons[monitorName]
  711.  
  712. local nextButtonSelected = (x >= v.next.startX and x <= v.next.endX) and (y >= v.next.startY and y <= v.next.endY)
  713. local prevButtonSelected = (x >= v.prev.startX and x <= v.prev.endX) and (y >= v.prev.startY and y <= v.prev.endY)
  714.  
  715. if nextButtonSelected then
  716. return "next"
  717. elseif prevButtonSelected then
  718. return "prev"
  719. end
  720.  
  721. return nil
  722. end
  723.  
  724. -- information window for the capacitors
  725.  
  726.  
  727. -- main display
  728. local function renderPaginationButtons(monitorName, max)
  729. local width, height = term.getSize()
  730. local nextButton = " Next "
  731. local previousButton = " Prev "
  732. local spacer = " "
  733.  
  734. local dashboardButtonsToRender = previousButton..spacer..nextButton
  735. local buttonOffset = (width - (string.len(dashboardButtonsToRender))) / 2
  736.  
  737. term.setCursorPos(buttonOffset, height)
  738. local x, y = getCursorPositionRelativeToParent(term.current())
  739.  
  740. if dashboardButtons[monitorName] == nil then
  741. dashboardButtons[monitorName] = {
  742. prev = {
  743. startX = x,
  744. startY = y,
  745. endX = x,
  746. endY = y
  747. },
  748.  
  749. next = {
  750. startX = x,
  751. startY = y,
  752. endX = x,
  753. endY = y
  754. },
  755.  
  756. offset = 1,
  757. max = max
  758. }
  759. end
  760.  
  761. if dashboardButtons[monitorName].offset == 1 then
  762. dashboardButtons[monitorName].max = max
  763. end
  764.  
  765. term.setBackgroundColor(colors.red)
  766. term.write(previousButton)
  767. dashboardButtons[monitorName].prev.endX, dashboardButtons[monitorName].prev.endY = getCursorPositionRelativeToParent(term.current())
  768.  
  769. term.setBackgroundColor(colors.black)
  770. term.write(spacer)
  771.  
  772. dashboardButtons[monitorName].next.startX, dashboardButtons[monitorName].next.startY = getCursorPositionRelativeToParent(term.current())
  773. term.setBackgroundColor(colors.red)
  774. term.write(nextButton)
  775. dashboardButtons[monitorName].next.endX, dashboardButtons[monitorName].next.endY = getCursorPositionRelativeToParent(term.current())
  776.  
  777. term.setBackgroundColor(colors.black)
  778. end
  779.  
  780. local function writeSummary(monitorName, totalEnergyAvailable, totalCapacity, totalFlowRate)
  781. local width, height = term.getSize()
  782. local gridLabel = os.getComputerLabel() or "| Power Monitor |"
  783. local gridLabelOffset = (width - (string.len(gridLabel))) / 2
  784.  
  785. term.setCursorPos(gridLabelOffset, 1)
  786. term.write(gridLabel)
  787. term.setCursorPos(1, 3)
  788.  
  789. print(padRight("Max Energy: "..totalCapacity.." RF"))
  790.  
  791. local totalPercentRemaining = math.floor((totalEnergyAvailable / totalCapacity) * 100)
  792. emitRedstoneSignalOnLowPower(totalPercentRemaining)
  793.  
  794. printZoneText(totalPercentRemaining, function() print(padRight("Available: "..totalEnergyAvailable.." RF")) end)
  795.  
  796. if totalFlowRate < 0 then
  797. term.setTextColor(colors.red)
  798. elseif totalFlowRate > 0 then
  799. term.setTextColor(colors.green)
  800. else
  801. term.setTextColor(colors.white)
  802. end
  803.  
  804. print(padRight("Flow Rate: "..totalFlowRate.." RF/t"))
  805. term.setTextColor(colors.white)
  806.  
  807. local currentX, currentY = term.getCursorPos()
  808. term.setCursorPos(1, currentY+1)
  809.  
  810. clickableLines[monitorName] = {}
  811. local pagination = dashboardButtons[monitorName] or {}
  812. local offset = pagination.offset or 1
  813.  
  814. local count = 0
  815. for i = offset, #capacitors do
  816. local v = capacitors[i]
  817. local name = string.format(" %03d", i)..": "
  818. local percent = v.percent
  819.  
  820. printZoneText(percent, function() term.write(name) end)
  821.  
  822. local labelLength = string.len(name)
  823. local powerBarLength = width - labelLength - 1
  824. local powerBarReading = math.floor((width - labelLength - 1) * (percent/100))
  825.  
  826. local zoneColor = colors.red
  827. local textColor = colors.white
  828. if percent >= GREEN_ZONE then
  829. zoneColor = colors.green
  830. elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
  831. zoneColor = colors.yellow
  832. textColor = colors.blue
  833. end
  834.  
  835. local stats = padRight(string.format(" %d", percent).."%, "..v.flowRate.." RF/t", powerBarLength)
  836.  
  837. term.setTextColor(textColor)
  838. term.setBackgroundColor(zoneColor)
  839. j = 1
  840. for c in stats:gmatch(".") do
  841. if(j>powerBarReading) then
  842. term.setBackgroundColor(colors.black)
  843. end
  844.  
  845. term.write(c)
  846.  
  847. j = j + 1
  848. end
  849. term.setTextColor(colors.white)
  850. term.setBackgroundColor(colors.black)
  851.  
  852. local currentX, currentY = getCursorPositionRelativeToParent(term.current())
  853. addClickableLine(monitorName, v.name, currentY)
  854.  
  855. local termX, termY = term.getCursorPos()
  856. term.setCursorPos(1, termY+2)
  857. count = count + 1
  858.  
  859. if termY > (height - 4) then
  860. max = count
  861. break
  862. end
  863. end
  864.  
  865. local currentX, currentY = term.getCursorPos()
  866. for k = currentY, height-1 do
  867. term.setCursorPos(1, k)
  868. term.clearLine()
  869. end
  870.  
  871. renderPaginationButtons(monitorName, count)
  872. end
  873.  
  874. local function displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, targetMonitor)
  875. local listOfSummaryWindows = {
  876. native = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
  877. }
  878.  
  879. for k, v in pairs(monitors) do
  880. listOfSummaryWindows[k] = v.windows.getSummaryWindow()
  881. end
  882.  
  883. for k, v in pairs(listOfSummaryWindows) do
  884. if targetMonitor == nil or (k == targetMonitor) then
  885. local currentTerm = term.current()
  886.  
  887. term.redirect(v)
  888.  
  889. writeSummary(k, totalEnergyAvailable, totalCapacity, totalFlowRate)
  890.  
  891. term.redirect(currentTerm)
  892.  
  893. if k == targetMonitor then
  894. return
  895. end
  896. end
  897. end
  898. end
  899.  
  900. local function monitorCapacitors()
  901. totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
  902.  
  903. while true do
  904. -- show reading
  905. displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate)
  906.  
  907. -- need to call this first to get most current sample
  908. getReading()
  909.  
  910. local samplingTimer = os.startTimer(PAUSE_TIME_IN_SECONDS)
  911. while true do
  912. local event, p1 = os.pullEvent()
  913. if event == "timer" and p1 == samplingTimer then
  914. totalEnergyAvailable, totalCapacity, totalFlowRate = getReading()
  915. break
  916. elseif event == "pause_monitor" then
  917. os.pullEvent("resume_monitor")
  918. break
  919. end
  920. end
  921. end
  922. end
  923.  
  924. local function changePages(monitor, x, y, isInformationWindowActive)
  925. local selectedButton = getSelectedDashboardButton(monitor, x, y)
  926. local showSummary = false
  927.  
  928. if selectedButton == "next" and not isInformationWindowActive then
  929. local newOffset = dashboardButtons[monitor].offset + (dashboardButtons[monitor].max or 0)
  930. if newOffset <= #capacitors then
  931. dashboardButtons[monitor].offset = newOffset
  932.  
  933. showSummary = true
  934. end
  935. elseif selectedButton == "prev" and not isInformationWindowActive then
  936. local newOffset = dashboardButtons[monitor].offset - (dashboardButtons[monitor].max or 0)
  937. if newOffset > 0 then
  938. dashboardButtons[monitor].offset = newOffset
  939. else
  940. dashboardButtons[monitor].offset = 1
  941. end
  942.  
  943. showSummary = true
  944. end
  945.  
  946. if showSummary then
  947. displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, p1)
  948. return true
  949. end
  950.  
  951. return false
  952. end
  953.  
  954. local function nativeDashboardHandler()
  955. while true do
  956. local event, x, y = os.pullEvent("dashboard_clicked")
  957. local isInformationWindowActive = nativeDisplayTabs.getDashboardWindows().getInformationWindow().active
  958.  
  959. if not changePages("native", x, y, isInformationWindowActive) then
  960. local selectedCapacitor = checkForSelectableLine("native", x, y)
  961.  
  962. local summaryWindow = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
  963. local informationWindow = nativeDisplayTabs.getDashboardWindows().getInformationWindow()
  964.  
  965. toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
  966. end
  967. end
  968. end
  969.  
  970. local function monitorDashboardHandler()
  971. while true do
  972. local event, monitor, x, y = os.pullEvent("monitor_touch")
  973.  
  974. if monitors[monitor].active == true then
  975. local summaryWindow = monitors[monitor].windows.getSummaryWindow()
  976. local informationWindow = monitors[monitor].windows.getInformationWindow()
  977.  
  978. if not changePages(monitor, x, y, informationWindow.active) then
  979. local selectedCapacitor = checkForSelectableLine(monitor, x, y)
  980. toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
  981. end
  982. end
  983. end
  984. end
  985. -- main display
  986.  
  987.  
  988. -- monitor selection screen (if monitor is attached)
  989. local function addClickableOutputMonitor(k, currentY)
  990. clickableOutputMonitors[k] = {
  991. line = currentY
  992. }
  993. end
  994.  
  995. local function toggleMonitor(monitorName)
  996. monitors[monitorName].active = not monitors[monitorName].active
  997.  
  998. if monitors[monitorName].active then
  999. console.log("Enabling "..monitorName)
  1000. MONITORS_ACTIVE[monitorName] = true
  1001. else
  1002. console.log("Disabling "..monitorName)
  1003. MONITORS_ACTIVE[monitorName] = nil
  1004.  
  1005. hideWindows(unpack(monitors[monitorName].windows))
  1006. monitors[monitorName].peripheral.setBackgroundColor(colors.black)
  1007. monitors[monitorName].peripheral.clear()
  1008. end
  1009.  
  1010. saveSettings()
  1011. end
  1012.  
  1013. local function showMonitorSelection(targetWindow)
  1014. local currentTerm = term.current()
  1015.  
  1016. term.redirect(targetWindow)
  1017. term.setCursorPos(1, 1)
  1018. term.clear()
  1019.  
  1020. local width, height = term.getSize()
  1021.  
  1022. if tableSize(monitors) > 0 then
  1023. printToWindow(term, 0, "Select Output Monitor: ")
  1024. else
  1025. printToWindow(term, 0, "No Monitors found.")
  1026. end
  1027.  
  1028. printToWindow(term, 0, "")
  1029.  
  1030. local currentX, currentY = term.getCursorPos()
  1031. term.setCursorPos(currentX + 2, currentY)
  1032.  
  1033. clickableOutputMonitors = {}
  1034. for k, v in pairs(monitors) do
  1035. currentX, currentY = getCursorPositionRelativeToParent(targetWindow)
  1036. term.setBackgroundColor(colors.black)
  1037.  
  1038. if v.active == true then
  1039. term.setBackgroundColor(colors.blue)
  1040. showWindows(unpack(v.windows))
  1041. end
  1042.  
  1043. label = padRight(" "..k, width-4)
  1044. printToWindow(term, 0, label)
  1045.  
  1046. addClickableOutputMonitor(k, currentY)
  1047. end
  1048. term.setBackgroundColor(colors.black)
  1049.  
  1050. term.redirect(currentTerm)
  1051.  
  1052. while true do
  1053. local event, x, y = os.pullEvent()
  1054.  
  1055. if "monitors_clicked" == event then
  1056. for k, v in pairs(clickableOutputMonitors) do
  1057. if v.line == y then
  1058. toggleMonitor(k)
  1059. return
  1060. end
  1061. end
  1062. elseif event == "peripheral" or event == "peripheral_detach" then
  1063. coroutine.yield()
  1064. return
  1065. end
  1066. end
  1067. end
  1068.  
  1069. local function monitorSelection()
  1070. for k, v in pairs(MONITORS_ACTIVE) do
  1071. if monitors[k] then
  1072. monitors[k].active = true
  1073. end
  1074. end
  1075.  
  1076. while true do
  1077. showMonitorSelection(monitorSelectionWindow)
  1078. end
  1079. end
  1080.  
  1081. local function nativeDisplay()
  1082. while true do
  1083. local currentTerm = term.current()
  1084.  
  1085. term.redirect(nativeMonitorTabWindow)
  1086. nativeMonitorTabWindow.setVisible(true)
  1087.  
  1088. term.setCursorPos(1, 1)
  1089. term.setBackgroundColor(colors.gray)
  1090. term.clearLine()
  1091. term.setTextColor(colors.yellow)
  1092.  
  1093. for i, v in ipairs(nativeDisplayTabs) do
  1094. hideWindows(unpack(v.windows))
  1095. end
  1096.  
  1097. for i, v in ipairs(nativeDisplayTabs) do
  1098. local tab = v.tab
  1099. tab.startX, tab.startY = getCursorPositionRelativeToParent(term.current())
  1100.  
  1101. if tab.active then
  1102. term.setBackgroundColor(colors.black)
  1103. showWindows(unpack(v.windows))
  1104. else
  1105. term.setBackgroundColor(colors.gray)
  1106. end
  1107.  
  1108. term.write(" "..tab.label.." ")
  1109. tab.endX, tab.endY = getCursorPositionRelativeToParent(term.current())
  1110. end
  1111. term.setTextColor(colors.white)
  1112. term.redirect(currentTerm)
  1113.  
  1114. while true do
  1115. local event, selectedTab = os.pullEvent("selected_tab")
  1116.  
  1117. if selectedTab then
  1118. nativeDisplayTabs.setSelectedTab(selectedTab)
  1119. break
  1120. end
  1121. end
  1122. end
  1123. end
  1124.  
  1125. local function mouseClickEventMonitor()
  1126. while true do
  1127. local event, type, x, y = os.pullEvent("mouse_click")
  1128. local selectedTab = nativeDisplayTabs.getSelectedTab(x, y)
  1129.  
  1130. if selectedTab and nativeDisplayTabs.getDashboardWindows().getInformationWindow().active == false then
  1131. os.queueEvent("selected_tab", selectedTab)
  1132. elseif selectedTab == nil then
  1133. local activeTab = nativeDisplayTabs[nativeDisplayTabs.getActiveTab()]
  1134.  
  1135. os.queueEvent(activeTab.tab.event, x, y)
  1136. end
  1137. end
  1138. end
  1139.  
  1140. -- Initialization
  1141. initializeNativeDisplayTabs()
  1142. resetRedstoneState()
  1143. addCapacitors()
  1144. addMonitors()
  1145.  
  1146. while true do
  1147. parallel.waitForAll(mouseClickEventMonitor, nativeDisplay, monitorSelection, hotplugPeripherals, monitorCapacitors, nativeDashboardHandler, monitorDashboardHandler)
  1148. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement