kriNon

Untitled

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