kriNon

Untitled

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