kriNon

Untitled

Dec 29th, 2015
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.33 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. while true do
  257. local function resetRedstoneState()
  258. for k,v in pairs(rs.getSides()) do
  259. rs.setOutput(v, false)
  260. end
  261. end
  262. end
  263. -- basic functions
  264.  
  265.  
  266. -- line drawing API
  267. local function drawVerticalLine(targetWindow, x, y, height)
  268. targetWindow.setCursorPos(x, y)
  269.  
  270. targetWindow.setBackgroundColor(colors.blue)
  271. for i = 1, height do
  272. targetWindow.write(" ")
  273. targetWindow.setCursorPos(x, i)
  274. end
  275. targetWindow.setBackgroundColor(colors.black)
  276. end
  277.  
  278. local function drawHorizontalLine(targetWindow, x, y, width)
  279. targetWindow.setCursorPos(x, y)
  280. targetWindow.setBackgroundColor(colors.blue)
  281. targetWindow.write(string.rep(" ", width))
  282. targetWindow.setBackgroundColor(colors.black)
  283. end
  284. -- line drawing API
  285.  
  286.  
  287. -- window management
  288. local console = {
  289. log = function(message)
  290. local currentTerm = term.current()
  291. term.redirect(consoleWindow)
  292.  
  293. print(message)
  294.  
  295. term.redirect(currentTerm)
  296. end
  297. }
  298.  
  299. local function showWindows(...)
  300. for i, v in ipairs(arg) do
  301. if v.active == true then
  302. v.setVisible(true)
  303. else
  304. v.setVisible(false)
  305. end
  306. end
  307. end
  308.  
  309. local function hideWindows(...)
  310. for i, v in ipairs(arg) do
  311. v.setVisible(false)
  312. end
  313. end
  314.  
  315. local function getCursorPositionRelativeToParent(currentWindow)
  316. -- determine offset of current window from parent
  317. local x, y = currentWindow.getPosition()
  318. local xOffset, yOffset = x - 1, y - 1
  319.  
  320. local cursorX, cursorY = currentWindow.getCursorPos()
  321. return cursorX + xOffset, cursorY + yOffset
  322. end
  323.  
  324. local function createInformationWindow(parentWindow)
  325. local width, height = parentWindow.getSize()
  326.  
  327. local widthOffset = 2
  328. local heightOffset = 2
  329.  
  330. local windowWidth = width - (widthOffset * 2)
  331. local windowHeight = height - (heightOffset * 2)
  332.  
  333. local informationWindow = window.create(parentWindow, 1 + widthOffset, 1 + heightOffset, windowWidth, windowHeight, false)
  334. informationWindow.active = false
  335.  
  336. drawHorizontalLine(informationWindow, 1, 1, windowWidth)
  337. drawHorizontalLine(informationWindow, 1, windowHeight, windowWidth)
  338.  
  339. drawVerticalLine(informationWindow, 1, 1, windowHeight)
  340. drawVerticalLine(informationWindow, windowWidth, 1, windowHeight)
  341.  
  342. return informationWindow
  343. end
  344.  
  345. local function createSummaryWindow(parentWindow, x, y)
  346. local width, height = parentWindow.getSize()
  347.  
  348. -- we make use of the parent window's cursor position to make it more convenient.
  349. local x, y = parentWindow.getCursorPos()
  350. local newHeight = height - (y - 1)
  351.  
  352. local summaryWindow = window.create(parentWindow, x, y, width, newHeight, false)
  353. summaryWindow.active = false
  354.  
  355. return summaryWindow
  356. end
  357.  
  358. local function printToWindow(targetWindow, widthOffset, text)
  359. local x, y = targetWindow.getCursorPos()
  360. local width, height = targetWindow.getSize()
  361. local maxTextSize = width - (widthOffset * 2)
  362.  
  363. targetWindow.write(text:sub(1, maxTextSize))
  364. targetWindow.setCursorPos(x, y+1)
  365. end
  366.  
  367. local function createDashboardWindows(parentWindow)
  368. -- order is important here!
  369. local summaryWindow = createSummaryWindow(parentWindow)
  370. summaryWindow.active = true
  371. local informationWindow = createInformationWindow(parentWindow)
  372. informationWindow.active = false
  373.  
  374. local windows = {
  375. [1] = summaryWindow,
  376. [2] = informationWindow,
  377.  
  378. getSummaryWindow = function()
  379. return summaryWindow
  380. end,
  381.  
  382. getInformationWindow = function()
  383. return informationWindow
  384. end
  385. }
  386.  
  387. return windows
  388. end
  389.  
  390. local function initializeNativeDisplayTabs()
  391. local nativeTerm = term.native()
  392. nativeTerm.setCursorPos(1, 2)
  393.  
  394. local dashboardWindows = createDashboardWindows(nativeTerm)
  395.  
  396. table.insert(nativeDisplayTabs, {
  397. tab = {
  398. label = "Dashboard",
  399. event = "dashboard_clicked",
  400. active = true,
  401. startX = 0,
  402. startY = 0
  403. },
  404.  
  405. windows = dashboardWindows
  406. })
  407. table.insert(nativeDisplayTabs, {
  408. tab = {
  409. label = "Monitors",
  410. event = "monitors_clicked",
  411. startX = 0,
  412. startY = 0
  413. },
  414.  
  415. windows = { monitorSelectionWindow }
  416. })
  417. table.insert(nativeDisplayTabs, {
  418. tab = {
  419. label = "Console",
  420. event = "console_clicked",
  421. startX = 0,
  422. startY = 0
  423. },
  424.  
  425. windows = { consoleWindow }
  426. })
  427.  
  428. nativeDisplayTabs.getSelectedTab = function(x, y)
  429. if x == nil or y == nil then
  430. return nil
  431. end
  432.  
  433. for i, v in ipairs(nativeDisplayTabs) do
  434. local tab = v.tab
  435. local withinX = x >= tab.startX and x <= tab.endX
  436. local withinY = y >= tab.startY and y <= tab.endY
  437.  
  438. if withinX and withinY then
  439. return i
  440. end
  441. end
  442.  
  443. return nil
  444. end
  445.  
  446. nativeDisplayTabs.setSelectedTab = function(selected)
  447. for i, v in ipairs(nativeDisplayTabs) do
  448. if i == selected then
  449. v.tab.active = true
  450. else
  451. v.tab.active = false
  452. end
  453. end
  454. end
  455.  
  456. nativeDisplayTabs.getActiveTab = function()
  457. for i, v in ipairs(nativeDisplayTabs) do
  458. if v.tab.active == true then
  459. return i
  460. end
  461. end
  462. end
  463.  
  464. nativeDisplayTabs.getDashboardWindows = function()
  465. return dashboardWindows
  466. end
  467. end
  468.  
  469. -- window management
  470.  
  471.  
  472. --Name check
  473.  
  474. local function findPeripheral(_type)
  475. for _,name in pairs(peripheral.getNames()) do
  476. if peripheral.getType(name) == _type then
  477. return peripheral.wrap(name)
  478. end
  479. end
  480. end
  481.  
  482. --TODO
  483.  
  484. -- capacitor management
  485. local function addCapacitors(...)
  486. local peripheralList = arg
  487.  
  488.  
  489. if #peripheralList == 0 then
  490. peripheralList = peripheral.getNames()
  491. capacitors.clear()
  492. end
  493.  
  494. for i, p in ipairs(peripheralList) do
  495. local currentPeripheral = peripheral.wrap(p)
  496.  
  497.  
  498. if currentPeripheral[GET_ENERGY_STORED_FUNCTION_MFSU] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU] ~= nil then
  499. console.log("Adding new capacitor: "..p)
  500. capacitors.add({
  501. name = p,
  502. peripheral = currentPeripheral,
  503. lastReading = 0,
  504. flowRate = 0,
  505. percent = 0
  506. })
  507. end
  508.  
  509.  
  510. end
  511. end
  512.  
  513. local function removeCapacitors(...)
  514. for i, k in ipairs(arg) do
  515. capacitors.remove(k)
  516. end
  517. end
  518.  
  519. local function getReading()
  520. local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
  521.  
  522. local currentReading = 0
  523. local capacity = 0
  524.  
  525. for i, v in ipairs(capacitors) do
  526.  
  527.  
  528. currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]() or 0
  529. capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU]() or 0
  530.  
  531. --error(currentReading)
  532. if currentReading ~= nil then
  533. v.flowRate = (currentReading - v.lastReading) / TICK_DELAY
  534. v.lastReading = currentReading
  535.  
  536. if capacity == 0 then
  537. v.percent = 0
  538. else
  539. v.percent = math.floor((currentReading / capacity) * 100)
  540. end
  541.  
  542. totalEnergyAvailable = totalEnergyAvailable + v.lastReading
  543. totalFlowRate = totalFlowRate + v.flowRate
  544. end
  545.  
  546. totalCapacity = totalCapacity + capacity
  547. end
  548.  
  549. local sortByLastReading = function(a, b)
  550. return a.percent > b.percent
  551. end
  552.  
  553. table.sort(capacitors, sortByLastReading)
  554.  
  555. return totalEnergyAvailable, totalCapacity, totalFlowRate
  556. end
  557.  
  558. local function emitRedstoneSignalOnLowPower(percent)
  559. if rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == false then
  560. rs.setAnalogOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, ((percent / 100)* 15))
  561. end
  562. end
  563. -- capacitor management
  564.  
  565.  
  566. -- monitor management
  567. local function addMonitors(...)
  568. local monitorList = arg
  569.  
  570. if #monitorList == 0 then
  571. monitorList = peripheral.getNames()
  572. monitors = {}
  573. end
  574.  
  575. for i, m in ipairs(monitorList) do
  576. local currentPeripheral = peripheral.wrap(m)
  577.  
  578. if "monitor" == peripheral.getType(m) and currentPeripheral.isColour() == true then
  579. console.log("Adding new monitor: "..m)
  580. currentPeripheral.setCursorPos(1, 1)
  581. monitors[m] = {
  582. peripheral = currentPeripheral,
  583. windows = createDashboardWindows(currentPeripheral),
  584. active = false
  585. }
  586. end
  587. end
  588. end
  589.  
  590. local function removeMonitors(...)
  591. local activeMonitorsCount = tableSize(MONITORS_ACTIVE)
  592.  
  593. for i, k in ipairs(arg) do
  594. monitors[k] = nil
  595. dashboardButtons[k] = nil
  596. MONITORS_ACTIVE[k] = nil
  597. end
  598.  
  599. if activeMonitorsCount ~= tableSize(MONITORS_ACTIVE) then
  600. saveSettings()
  601. end
  602. end
  603. -- monitor management
  604.  
  605.  
  606. -- hotplug system
  607. local function doWhileMonitorSuspended(callback)
  608. os.queueEvent("pause_monitor")
  609. callback()
  610. os.queueEvent("resume_monitor")
  611. end
  612.  
  613. local function hotplugPeripherals()
  614. while true do
  615. local event, name = os.pullEvent()
  616. local callback = nil
  617.  
  618. if event == "peripheral" then
  619. console.log("Detected new peripheral: "..name)
  620.  
  621. callback = function()
  622. addMonitors(name)
  623. addCapacitors(name)
  624. end
  625. elseif event == "peripheral_detach" then
  626. console.log("Peripheral removed: "..name)
  627.  
  628. callback = function()
  629. removeMonitors(name)
  630. removeCapacitors(name)
  631. end
  632. elseif event == "monitor_resize" then
  633. console.log("Monitor resized: "..name)
  634.  
  635. callback = function()
  636. monitors[name].peripheral.setCursorPos(1, 1)
  637. monitors[name].windows = createDashboardWindows(monitors[name].peripheral)
  638. dashboardButtons[name] = nil
  639.  
  640. if monitors[name].active == true then
  641. showWindows(unpack(monitors[name].windows))
  642. end
  643. end
  644. end
  645.  
  646. if callback ~= nil then
  647. doWhileMonitorSuspended(callback)
  648. end
  649. end
  650. end
  651. -- hotplug system
  652.  
  653.  
  654. -- information window for the capacitors
  655. local function addClickableLine(monitorName, key, currentY)
  656. clickableLines[monitorName][key] = {
  657. line = currentY
  658. }
  659. end
  660.  
  661. local function toggleInformationWindow(summaryWindow, informationWindow, capacitorName)
  662. if capacitorName == nil then
  663. summaryWindow.active = true
  664. informationWindow.active = false
  665. else
  666. summaryWindow.active = not summaryWindow.active
  667. informationWindow.active = not informationWindow.active
  668. end
  669.  
  670. local capacitor = capacitors.get(capacitorName)
  671.  
  672. if informationWindow.active == true then
  673. widthOffset = 3
  674. heightOffset = 3
  675.  
  676. informationWindow.setCursorPos(widthOffset, heightOffset)
  677. local width, height = informationWindow.getSize()
  678. local labelWidth = width - (widthOffset * 2)
  679. local capacity = 0
  680. --Capcacity
  681. if(findPeripheral("mfsu")) then
  682. capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU]()
  683. else
  684. capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north")
  685. end
  686. --Capacity
  687.  
  688.  
  689. printToWindow(informationWindow, widthOffset, "Capacitor name:")
  690. printToWindow(informationWindow, widthOffset, padRight(" "..capacitorName, labelWidth))
  691. printToWindow(informationWindow, widthOffset, "Capacitor type:")
  692. printToWindow(informationWindow, widthOffset, padRight(" "..peripheral.getType(capacitorName), labelWidth))
  693. printToWindow(informationWindow, widthOffset, "Capacity:")
  694. printToWindow(informationWindow, widthOffset, padRight(" "..capacity.." EU", labelWidth))
  695. printToWindow(informationWindow, widthOffset, "Available:")
  696. printToWindow(informationWindow, widthOffset, padRight(" "..capacitor.lastReading.." EU", labelWidth))
  697.  
  698. local closeLabel = " Click anywhere to close "
  699.  
  700. local x = math.floor(((width - string.len(closeLabel)) / 2 ) + 0.5)
  701.  
  702. informationWindow.setCursorPos(x, height-2)
  703.  
  704. informationWindow.setBackgroundColor(colors.red)
  705. informationWindow.write(closeLabel)
  706. informationWindow.setBackgroundColor(colors.black)
  707. end
  708.  
  709. showWindows(summaryWindow, informationWindow)
  710. end
  711.  
  712. local function checkForSelectableLine(monitorName, x, y)
  713. if clickableLines[monitorName] == nil then
  714. return nil
  715. end
  716.  
  717. for k,v in pairs(clickableLines[monitorName]) do
  718. if y == v.line then
  719. return k
  720. end
  721. end
  722.  
  723. return nil
  724. end
  725.  
  726. local function getSelectedDashboardButton(monitorName, x, y)
  727. if x == nil or y == nil then
  728. return nil
  729. end
  730.  
  731. local v = dashboardButtons[monitorName]
  732.  
  733. local nextButtonSelected = (x >= v.next.startX and x <= v.next.endX) and (y >= v.next.startY and y <= v.next.endY)
  734. local prevButtonSelected = (x >= v.prev.startX and x <= v.prev.endX) and (y >= v.prev.startY and y <= v.prev.endY)
  735.  
  736. if nextButtonSelected then
  737. return "next"
  738. elseif prevButtonSelected then
  739. return "prev"
  740. end
  741.  
  742. return nil
  743. end
  744.  
  745. -- information window for the capacitors
  746.  
  747.  
  748. -- main display
  749. local function renderPaginationButtons(monitorName, max)
  750. local width, height = term.getSize()
  751. local nextButton = " Next "
  752. local previousButton = " Prev "
  753. local spacer = " "
  754.  
  755. local dashboardButtonsToRender = previousButton..spacer..nextButton
  756. local buttonOffset = (width - (string.len(dashboardButtonsToRender))) / 2
  757.  
  758. term.setCursorPos(buttonOffset, height)
  759. local x, y = getCursorPositionRelativeToParent(term.current())
  760.  
  761. if dashboardButtons[monitorName] == nil then
  762. dashboardButtons[monitorName] = {
  763. prev = {
  764. startX = x,
  765. startY = y,
  766. endX = x,
  767. endY = y
  768. },
  769.  
  770. next = {
  771. startX = x,
  772. startY = y,
  773. endX = x,
  774. endY = y
  775. },
  776.  
  777. offset = 1,
  778. max = max
  779. }
  780. end
  781.  
  782. if dashboardButtons[monitorName].offset == 1 then
  783. dashboardButtons[monitorName].max = max
  784. end
  785.  
  786. term.setBackgroundColor(colors.red)
  787. term.write(previousButton)
  788. dashboardButtons[monitorName].prev.endX, dashboardButtons[monitorName].prev.endY = getCursorPositionRelativeToParent(term.current())
  789.  
  790. term.setBackgroundColor(colors.black)
  791. term.write(spacer)
  792.  
  793. dashboardButtons[monitorName].next.startX, dashboardButtons[monitorName].next.startY = getCursorPositionRelativeToParent(term.current())
  794. term.setBackgroundColor(colors.red)
  795. term.write(nextButton)
  796. dashboardButtons[monitorName].next.endX, dashboardButtons[monitorName].next.endY = getCursorPositionRelativeToParent(term.current())
  797.  
  798. term.setBackgroundColor(colors.black)
  799. end
  800.  
  801. local function writeSummary(monitorName, totalEnergyAvailable, totalCapacity, totalFlowRate)
  802. local width, height = term.getSize()
  803. local gridLabel = os.getComputerLabel() or "No name set"
  804. local gridLabelOffset = (width - (string.len(gridLabel))) / 2
  805.  
  806. term.setCursorPos(gridLabelOffset, 1)
  807. term.write(gridLabel)
  808. term.setCursorPos(1, 3)
  809.  
  810. print(padRight("Total Capacitors: "..tostring(#capacitors)))
  811. print(padRight("Max Energy Storage: "..totalCapacity.." EU"))
  812.  
  813. local totalPercentRemaining = math.floor((totalEnergyAvailable / totalCapacity) * 100)
  814. emitRedstoneSignalOnLowPower(totalPercentRemaining)
  815.  
  816. if totalEnergyAvailable > totalCapacity then
  817. printZoneText(totalPercentRemaining, function() print(padRight("Energy Available: "..totalCapacity.." EU")) end)
  818. else
  819. printZoneText(totalPercentRemaining, function() print(padRight("Energy Available: "..totalEnergyAvailable.." EU")) end)
  820. end
  821.  
  822.  
  823. if totalFlowRate < 0 then
  824. term.setTextColor(colors.red)
  825. elseif totalFlowRate > 0 then
  826. term.setTextColor(colors.green)
  827. else
  828. term.setTextColor(colors.white)
  829. end
  830.  
  831. print(padRight("Flow Rate: "..totalFlowRate.." EU/t"))
  832. term.setTextColor(colors.white)
  833.  
  834. local currentX, currentY = term.getCursorPos()
  835. term.setCursorPos(1, currentY+1)
  836.  
  837. clickableLines[monitorName] = {}
  838. local pagination = dashboardButtons[monitorName] or {}
  839. local offset = pagination.offset or 1
  840.  
  841. local count = 0
  842. for i = offset, #capacitors do
  843. local v = capacitors[i]
  844. local name = string.format(" %03d", i)..": "
  845. local percent = v.percent
  846.  
  847. printZoneText(percent, function() term.write(name) end)
  848.  
  849. local labelLength = string.len(name)
  850. local powerBarLength = width - labelLength - 1
  851. local powerBarReading = math.floor((width - labelLength - 1) * (percent/100))
  852.  
  853. local zoneColor = colors.red
  854. local textColor = colors.white
  855. if percent >= GREEN_ZONE then
  856. zoneColor = colors.green
  857. elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
  858. zoneColor = colors.yellow
  859. textColor = colors.blue
  860. end
  861.  
  862. local stats = padRight(string.format(" %d", percent).."%, "..v.flowRate.." EU/t", powerBarLength)
  863.  
  864. term.setTextColor(textColor)
  865. term.setBackgroundColor(zoneColor)
  866. j = 1
  867. for c in stats:gmatch(".") do
  868. if(j>powerBarReading) then
  869. term.setBackgroundColor(colors.black)
  870. end
  871.  
  872. term.write(c)
  873.  
  874. j = j + 1
  875. end
  876. term.setTextColor(colors.white)
  877. term.setBackgroundColor(colors.black)
  878.  
  879. local currentX, currentY = getCursorPositionRelativeToParent(term.current())
  880. addClickableLine(monitorName, v.name, currentY)
  881.  
  882. local termX, termY = term.getCursorPos()
  883. term.setCursorPos(1, termY+2)
  884. count = count + 1
  885.  
  886. if termY > (height - 4) then
  887. max = count
  888. break
  889. end
  890. end
  891.  
  892. local currentX, currentY = term.getCursorPos()
  893. for k = currentY, height-1 do
  894. term.setCursorPos(1, k)
  895. term.clearLine()
  896. end
  897.  
  898. renderPaginationButtons(monitorName, count)
  899. end
  900.  
  901. local function displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, targetMonitor)
  902. local listOfSummaryWindows = {
  903. native = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
  904. }
  905.  
  906. for k, v in pairs(monitors) do
  907. listOfSummaryWindows[k] = v.windows.getSummaryWindow()
  908. end
  909.  
  910. for k, v in pairs(listOfSummaryWindows) do
  911. if targetMonitor == nil or (k == targetMonitor) then
  912. local currentTerm = term.current()
  913.  
  914. term.redirect(v)
  915.  
  916. writeSummary(k, totalEnergyAvailable, totalCapacity, totalFlowRate)
  917.  
  918. term.redirect(currentTerm)
  919.  
  920. if k == targetMonitor then
  921. return
  922. end
  923. end
  924. end
  925. end
  926.  
  927. local function monitorCapacitors()
  928. totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
  929.  
  930. while true do
  931. -- show reading
  932. displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate)
  933.  
  934. -- need to call this first to get most current sample
  935. getReading()
  936.  
  937. local samplingTimer = os.startTimer(PAUSE_TIME_IN_SECONDS)
  938. while true do
  939. local event, p1 = os.pullEvent()
  940. if event == "timer" and p1 == samplingTimer then
  941. totalEnergyAvailable, totalCapacity, totalFlowRate = getReading()
  942. break
  943. elseif event == "pause_monitor" then
  944. os.pullEvent("resume_monitor")
  945. break
  946. end
  947. end
  948. end
  949. end
  950.  
  951. local function changePages(monitor, x, y, isInformationWindowActive)
  952. local selectedButton = getSelectedDashboardButton(monitor, x, y)
  953. local showSummary = false
  954.  
  955. if selectedButton == "next" and not isInformationWindowActive then
  956. local newOffset = dashboardButtons[monitor].offset + (dashboardButtons[monitor].max or 0)
  957. if newOffset <= #capacitors then
  958. dashboardButtons[monitor].offset = newOffset
  959.  
  960. showSummary = true
  961. end
  962. elseif selectedButton == "prev" and not isInformationWindowActive then
  963. local newOffset = dashboardButtons[monitor].offset - (dashboardButtons[monitor].max or 0)
  964. if newOffset > 0 then
  965. dashboardButtons[monitor].offset = newOffset
  966. else
  967. dashboardButtons[monitor].offset = 1
  968. end
  969.  
  970. showSummary = true
  971. end
  972.  
  973. if showSummary then
  974. displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, p1)
  975. return true
  976. end
  977.  
  978. return false
  979. end
  980.  
  981. local function nativeDashboardHandler()
  982. while true do
  983. local event, x, y = os.pullEvent("dashboard_clicked")
  984. local isInformationWindowActive = nativeDisplayTabs.getDashboardWindows().getInformationWindow().active
  985.  
  986. if not changePages("native", x, y, isInformationWindowActive) then
  987. local selectedCapacitor = checkForSelectableLine("native", x, y)
  988.  
  989. local summaryWindow = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
  990. local informationWindow = nativeDisplayTabs.getDashboardWindows().getInformationWindow()
  991.  
  992. toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
  993. end
  994. end
  995. end
  996.  
  997. local function monitorDashboardHandler()
  998. while true do
  999. local event, monitor, x, y = os.pullEvent("monitor_touch")
  1000.  
  1001. if monitors[monitor].active == true then
  1002. local summaryWindow = monitors[monitor].windows.getSummaryWindow()
  1003. local informationWindow = monitors[monitor].windows.getInformationWindow()
  1004.  
  1005. if not changePages(monitor, x, y, informationWindow.active) then
  1006. local selectedCapacitor = checkForSelectableLine(monitor, x, y)
  1007. toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
  1008. end
  1009. end
  1010. end
  1011. end
  1012. -- main display
  1013.  
  1014.  
  1015. -- monitor selection screen (if monitor is attached)
  1016. local function addClickableOutputMonitor(k, currentY)
  1017. clickableOutputMonitors[k] = {
  1018. line = currentY
  1019. }
  1020. end
  1021.  
  1022. local function toggleMonitor(monitorName)
  1023. monitors[monitorName].active = not monitors[monitorName].active
  1024.  
  1025. if monitors[monitorName].active then
  1026. console.log("Enabling "..monitorName)
  1027. MONITORS_ACTIVE[monitorName] = true
  1028. else
  1029. console.log("Disabling "..monitorName)
  1030. MONITORS_ACTIVE[monitorName] = nil
  1031.  
  1032. hideWindows(unpack(monitors[monitorName].windows))
  1033. monitors[monitorName].peripheral.setBackgroundColor(colors.black)
  1034. monitors[monitorName].peripheral.clear()
  1035. end
  1036.  
  1037. saveSettings()
  1038. end
  1039.  
  1040. local function showMonitorSelection(targetWindow)
  1041. local currentTerm = term.current()
  1042.  
  1043. term.redirect(targetWindow)
  1044. term.setCursorPos(1, 1)
  1045. term.clear()
  1046.  
  1047. local width, height = term.getSize()
  1048.  
  1049. if tableSize(monitors) > 0 then
  1050. printToWindow(term, 0, "Select Output Monitor: ")
  1051. else
  1052. printToWindow(term, 0, "No Monitors found.")
  1053. end
  1054.  
  1055. printToWindow(term, 0, "")
  1056.  
  1057. local currentX, currentY = term.getCursorPos()
  1058. term.setCursorPos(currentX + 2, currentY)
  1059.  
  1060. clickableOutputMonitors = {}
  1061. for k, v in pairs(monitors) do
  1062. currentX, currentY = getCursorPositionRelativeToParent(targetWindow)
  1063. term.setBackgroundColor(colors.black)
  1064.  
  1065. if v.active == true then
  1066. term.setBackgroundColor(colors.blue)
  1067. showWindows(unpack(v.windows))
  1068. end
  1069.  
  1070. label = padRight(" "..k, width-4)
  1071. printToWindow(term, 0, label)
  1072.  
  1073. addClickableOutputMonitor(k, currentY)
  1074. end
  1075. term.setBackgroundColor(colors.black)
  1076.  
  1077. term.redirect(currentTerm)
  1078.  
  1079. while true do
  1080. local event, x, y = os.pullEvent()
  1081.  
  1082. if "monitors_clicked" == event then
  1083. for k, v in pairs(clickableOutputMonitors) do
  1084. if v.line == y then
  1085. toggleMonitor(k)
  1086. return
  1087. end
  1088. end
  1089. elseif event == "peripheral" or event == "peripheral_detach" then
  1090. coroutine.yield()
  1091. return
  1092. end
  1093. end
  1094. end
  1095.  
  1096. local function monitorSelection()
  1097. for k, v in pairs(MONITORS_ACTIVE) do
  1098. if monitors[k] then
  1099. monitors[k].active = true
  1100. end
  1101. end
  1102.  
  1103. while true do
  1104. showMonitorSelection(monitorSelectionWindow)
  1105. end
  1106. end
  1107.  
  1108. local function nativeDisplay()
  1109. while true do
  1110. local currentTerm = term.current()
  1111.  
  1112. term.redirect(nativeMonitorTabWindow)
  1113. nativeMonitorTabWindow.setVisible(true)
  1114.  
  1115. term.setCursorPos(1, 1)
  1116. term.setBackgroundColor(colors.gray)
  1117. term.clearLine()
  1118. term.setTextColor(colors.yellow)
  1119.  
  1120. for i, v in ipairs(nativeDisplayTabs) do
  1121. hideWindows(unpack(v.windows))
  1122. end
  1123.  
  1124. for i, v in ipairs(nativeDisplayTabs) do
  1125. local tab = v.tab
  1126. tab.startX, tab.startY = getCursorPositionRelativeToParent(term.current())
  1127.  
  1128. if tab.active then
  1129. term.setBackgroundColor(colors.black)
  1130. showWindows(unpack(v.windows))
  1131. else
  1132. term.setBackgroundColor(colors.gray)
  1133. end
  1134.  
  1135. term.write(" "..tab.label.." ")
  1136. tab.endX, tab.endY = getCursorPositionRelativeToParent(term.current())
  1137. end
  1138. term.setTextColor(colors.white)
  1139. term.redirect(currentTerm)
  1140.  
  1141. while true do
  1142. local event, selectedTab = os.pullEvent("selected_tab")
  1143.  
  1144. if selectedTab then
  1145. nativeDisplayTabs.setSelectedTab(selectedTab)
  1146. break
  1147. end
  1148. end
  1149. end
  1150. end
  1151.  
  1152. local function mouseClickEventMonitor()
  1153. while true do
  1154. local event, type, x, y = os.pullEvent("mouse_click")
  1155. local selectedTab = nativeDisplayTabs.getSelectedTab(x, y)
  1156.  
  1157. if selectedTab and nativeDisplayTabs.getDashboardWindows().getInformationWindow().active == false then
  1158. os.queueEvent("selected_tab", selectedTab)
  1159. elseif selectedTab == nil then
  1160. local activeTab = nativeDisplayTabs[nativeDisplayTabs.getActiveTab()]
  1161.  
  1162. os.queueEvent(activeTab.tab.event, x, y)
  1163. end
  1164. end
  1165. end
  1166.  
  1167. -- Initialization
  1168. initializeNativeDisplayTabs()
  1169. resetRedstoneState()
  1170. addCapacitors()
  1171. addMonitors()
  1172.  
  1173. while true do
  1174. parallel.waitForAll(mouseClickEventMonitor, nativeDisplay, monitorSelection, hotplugPeripherals, monitorCapacitors, nativeDashboardHandler, monitorDashboardHandler)
  1175. end
Advertisement
Add Comment
Please, Sign In to add comment