Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- This program lets you monitor and actively control a Big Reactors reactor and turbines with an OpenComputers computer.
- This program was tested on and designed to work with the mod versions and configurations installed on Flawedspirit's Mental Instability Pack, though as the pack uses default settings for both Big Reactors and OpenComputers, there should be no issues using a different modpack, or even a modpack that makes changes to how BR works.
- - http://technicpack.net/modpack/mi-reloaded.604813
- - https://flawedspirit.com/minecraft/#pack
- Computer Design
- ------------------------
- Please note that to keep the code (relatively) simple, the program makes a few assumptions; those being:
- - A Tier 3 Computer
- - A Tier 2 or better Graphics Card
- - An Internet Card
- - One Tier 2 screen OR one Tier 3 screen (for best results)
- - One reactor
- - Any number of (or zero) turbines
- Notes
- ------------------------
- - Only one reactor has been tested with this program (additional reactors added AT OWN RISK)
- - Data for only 6 turbines will display onscreen if using a Tier 2 screen
- - Data for up to 28 turbines will display onscreen if using a Tier 3 screen
- - Data for ALL turbines will still be tallied in the 'totals' row
- - By default, the program updates once every 2 seconds, though the rate is adjustable
- Features
- ------------------------
- - Dynamic tracking of reactor information, like temperature, fuel/waste levels, coolant levels*, steam output*, or RF storage*
- - Dynamic tracking of up to 6 turbines, including speed, steam input, RF generation, and RF storage
- - In-program control of reactor power and control rod settings
- - Real-time warning if certain parameters indicate abnormal or non-optimal operation of reactors/turbines
- - NEW! Turbine auto mode! Set it to either 900 or 1800 RPM by pressing T and the program will toggle your turbines' induction coils or active state to keep it at the right speed**
- * If applicable
- ** Note: the author takes no responsibility if you bankrupt your base's energy stores because your turbines are all disengaged. Please use responsibly.
- Usage
- ------------------------
- - Press the left and right arrow keys to toggle between page 1 (turbine/RF storage information) or 2 (control rod configuration)
- - Press L or , to lower/raise control rods by 1%
- - Press ; or . to lower/raise control rods by 5%
- - Press ' or / to lower/raise control rods by 10%
- - Press P to toggle reactor power
- - Press Q to exit the program and return to your computer's terminal prompt
- - Press T to toggle 'Auto Mode' on all turbines. This will engage the induction coil when your preferred rotational speed (900 or 1800 RPM) is reached
- Resources
- ------------------------
- - This script is available from:
- = http://pastebin.com/zWju7H0z
- - Official OpenComputers Site: http://ocdoc.cil.li/
- - Official Big Reactors Site: http://www.big-reactors.com/#/
- - Big Reactors API: http://wiki.technicpack.net/Reactor_Computer_Port
- Changelog
- ------------------------
- - 0.1.6
- - Fixed a bug that caused the program to crash when run on a Tier 2 screen
- - 0.1.5
- - Addition of turbine auto mode
- - Changes to make the program take better advantage of larger screen sizes
- - Bug fixes
- - 0.1.4
- - First release to Github! :D
- TODO
- ------------------------
- - See https://github.com/Flawedspirit/FlawedspiritOC/issues for any outstanding issues.
- - Fix screen flickering issue on Page 1 (may not be possible at the moment)
- ]]
- local component = require("component")
- local event = require("event")
- local keyboard = require("keyboard")
- local os = require("os")
- local term = require("term")
- local pollRate = 2 -- Change to whatever value you'd like; time is in seconds
- local active = true
- local currentPage = 1
- local turbineAutoMode = 0 -- This can be changed to 900 or 1800 if you want
- -- Static Text Elements
- local header = "Reactor: "
- local headerOutput = "Running at %d%% max rated output"
- local version = "v0.1.6"
- -- Components
- local gpu = component.gpu
- local reactor = component.br_reactor
- local w, h = gpu.getResolution()
- local turbine = {}
- local i = 1
- for address, type in component.list("br_turbine") do
- turbine[i] = component.proxy(address)
- i = i + 1
- end
- -- Reactor/turbine Data
- local totalControlRodLevel = 0
- local turbineMaxSteamIn = 0
- local controlRods = {}
- local reactorStatus = {}
- -- Colors Helper
- local colors = {}
- colors.white = 0xFFFFFF
- colors.orange = 0xFFA500
- colors.magenta = 0xFF00FF
- colors.lightblue = 0x00AEEF
- colors.yellow = 0xFFFF00
- colors.lime = 0x00FF00
- colors.pink = 0xFFC0CB
- colors.gray = 0x555555
- colors.grey = 0x555555
- colors.silver = 0xAAAAAA
- colors.cyan = 0x00FFFF
- colors.purple = 0x800080
- colors.blue = 0x0000FF
- colors.brown = 0x603913
- colors.green = 0x008000
- colors.red = 0xFF0000
- colors.black = 0x000000
- -- Returns a whole number expressing a percentage
- -- out of 100 e.g. 90 is 90%
- function percent(val, max)
- return (val / max) * 100
- end
- function hLine(row)
- gpu.fill(1, row, w, 1, "─")
- end
- function label(x, y, message, color, ...)
- local color = color or gpu.getForeground()
- local oldColor = gpu.getForeground()
- gpu.setForeground(color)
- term.setCursor(x, y)
- print(string.format(message, ...))
- gpu.setForeground(oldColor)
- end
- function box(row, message, color)
- --gpu.fill(1, row, w, row + 3, " ")
- local color = color or gpu.getForeground()
- local oldColor = gpu.getForeground()
- term.setCursor(1, row)
- gpu.setForeground(color)
- -- Corners
- gpu.set(1, row, "╒")
- gpu.set(w, row, "╕")
- gpu.set(1, row + 2, "└")
- gpu.set(w, row + 2, "┘")
- -- Left and right
- gpu.set(1, row + 1, "│")
- gpu.set(w, row + 1, "│")
- -- Top and bottom
- gpu.fill(2, row, w - 2, 1, "═")
- gpu.fill(2, row + 2, w - 2, 1, "─")
- gpu.set(3, row + 1, message)
- gpu.setForeground(oldColor)
- end
- -- Displayed if a reactor cannot be found at all
- -- and this program is rendered useless
- function printNoSignal()
- icon = "[ ! ] "
- message = "No Signal"
- gpu.setBackground(colors.black)
- gpu.fill(1, 1, w, h, " ")
- gpu.setForeground(colors.red)
- gpu.set(w / 2 - (string.len(icon) + string.len(message)) / 2 + 1, (h / 2) + 1, "[ ! ]")
- gpu.setForeground(colors.white)
- gpu.set((w / 2) - 1, (h / 2) + 1, message)
- end
- function printControlHelp()
- hLine(h - 5)
- label(1, h - 4, "%s", nil, "l / ,")
- label(16, h - 4, "%s", nil, "; / .")
- label(32, h - 4, "%s", nil, "' / /")
- label(48, h - 4, "%s", nil, "p")
- label(64, h - 4, "%s", nil, "q")
- label(1, h - 3, "%s", colors.gray, "Rods +1/-1")
- label(16, h - 3, "%s", colors.gray, "Rods +5/-5")
- label(32, h - 3, "%s", colors.gray, "Rods +10/-10")
- label(48, h - 3, "%s", colors.gray, "Reactor Power")
- label(64, h - 3, "%s", colors.gray, "Quit")
- if w > 80 then
- label(80, h - 4, "%s", nil, "t")
- label(80, h - 3, "%s", colors.gray, "Turbine Auto Mode")
- end
- end
- function toggleAutoMode()
- if turbineAutoMode == 0 then
- turbineAutoMode = 900
- elseif turbineAutoMode == 900 then
- turbineAutoMode = 1800
- elseif turbineAutoMode == 1800 then
- turbineAutoMode = 0
- else
- turbineAutoMode = 0
- end
- end
- -- Event handler for when a key is pressed
- function onKeyDown(key)
- local event, address, _, key, _ = event.pull()
- if key == keyboard.keys.right then
- currentPage = 2
- gpu.fill(1, 1, w, h, " ")
- elseif key == keyboard.keys.left then
- currentPage = 1
- gpu.fill(1, 1, w, h, " ")
- elseif key == keyboard.keys.l then
- reactor.setAllControlRodLevels(totalControlRodLevel + 1)
- elseif key == keyboard.keys.comma then
- reactor.setAllControlRodLevels(totalControlRodLevel - 1)
- elseif key == keyboard.keys.semicolon then
- reactor.setAllControlRodLevels(totalControlRodLevel + 5)
- elseif key == keyboard.keys.period then
- reactor.setAllControlRodLevels(totalControlRodLevel -5)
- elseif key == keyboard.keys.apostrophe then
- reactor.setAllControlRodLevels(totalControlRodLevel + 10)
- elseif key == keyboard.keys.slash then
- reactor.setAllControlRodLevels(totalControlRodLevel - 10)
- elseif key == keyboard.keys.p then
- reactor.setActive(not reactor.getActive())
- elseif key == keyboard.keys.q then
- active = false
- elseif key == keyboard.keys.t then
- toggleAutoMode()
- end
- end
- -- Listen for "key_down" event to control program flow
- event.listen("key_down", onKeyDown)
- while active do
- gpu.fill(1, 1, w, h, " ")
- if component.isAvailable("br_reactor") then
- label(w - (string.len(version) + 1), h - 1, version, colors.gray)
- box(1, header, nil)
- -- Get and update values of each control rod
- for i = 1, reactor.getNumberOfControlRods() - 1 do
- controlRods[i] = reactor.getControlRodLevel(i)
- end
- -- Iterate through and take the sum of each control rod level
- -- Average it to get total control rod level
- totalControlRodLevel = 0
- for i = 1, #controlRods do
- totalControlRodLevel = totalControlRodLevel + controlRods[i]
- end
- totalControlRodLevel = totalControlRodLevel / #controlRods
- -- Update reactor data
- reactorStatus.temperature = {"Temp", reactor.getCasingTemperature()}
- reactorStatus.fuel = {"Fuel", reactor.getFuelAmount()}
- reactorStatus.waste = {"Waste", reactor.getWasteAmount()}
- reactorStatus.fuelMax = {"Max Fuel", reactor.getFuelAmountMax()}
- reactorStatus.burnRate = {"Burn Rate", reactor.getFuelConsumedLastTick()}
- reactorStatus.reactivity = {"Reactivity", reactor.getFuelReactivity()}
- reactorStatus.coolant = {"Coolant", reactor.getCoolantAmount()}
- reactorStatus.coolantMax = {"Max Coolant", reactor.getCoolantAmountMax()}
- reactorStatus.steam = {"Steam Out", reactor.getHotFluidProducedLastTick()}
- reactorStatus.steamMax = {"Max Steam", reactor.getHotFluidAmountMax()}
- reactorStatus.storedRF = {"Stored Power", reactor.getEnergyStored()}
- label(1, 4, "%s: %.3f mB/t (%s: %d%%)", nil, reactorStatus.burnRate[1], reactorStatus.burnRate[2], reactorStatus.reactivity[1], reactorStatus.reactivity[2])
- -- REACTOR TABLE
- -- Table header
- label(1, 6, "%s", nil, reactorStatus.temperature[1])
- label(16, 6, "%s", nil, reactorStatus.fuel[1])
- label(32, 6, "%s", nil, reactorStatus.waste[1])
- label(48, 6, "%s", nil, reactorStatus.coolant[1])
- label(64, 6, "%s", nil, reactorStatus.steam[1])
- hLine(7)
- -- Table body
- label(1, 8, "%d °C", colors.red, reactorStatus.temperature[2])
- if percent(reactorStatus.fuel[2], reactorStatus.fuelMax[2]) > 10 then
- label(16, 8, "%d mB", nil, reactorStatus.fuel[2])
- else
- label(16, 8, "%d mB [!]", colors.red, reactorStatus.fuel[2])
- end
- if percent(reactorStatus.waste[2], reactorStatus.fuelMax[2]) < 90 then
- label(32, 8, "%d mB", nil, reactorStatus.waste[2])
- else
- label(32, 8, "%d mB [!]", colors.red, reactorStatus.waste[2])
- end
- if percent(reactorStatus.coolant[2], reactorStatus.coolantMax[2]) > 10 then
- label(48, 8, "%d mB", nil, reactorStatus.fuel[2])
- else
- label(48, 8, "%d mB [!]", colors.red, reactorStatus.coolant[2])
- end
- if reactorStatus.steam[2] >= turbineMaxSteamIn then
- label(64, 8, "%d mB/t", nil, reactorStatus.steam[2])
- else
- label(64, 8, "%d mB/t [!]", colors.red, reactorStatus.steam[2])
- end
- -- Percentages
- label(16, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.fuel[2], reactorStatus.fuelMax[2]))
- label(32, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.waste[2], reactorStatus.fuelMax[2]))
- label(48, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.coolant[2], reactorStatus.coolantMax[2]))
- label(64, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.steam[2], reactorStatus.steamMax[2]))
- if reactor.getActive() then
- label(string.len(header) + 3, 2, "ON", colors.lime)
- label(w - string.len(headerOutput), 2, headerOutput, nil, (100 - totalControlRodLevel))
- else
- label(string.len(header) + 3, 2, "OFF", colors.red)
- label((w + 1) - string.len(headerOutput), 2, headerOutput, nil, 0)
- end
- if currentPage == 1 then
- box(h - 2, "Press [→] to go to page 2", nil)
- if h > 25 then
- printControlHelp()
- end
- if component.isAvailable("br_turbine") then
- -- TURBINE TABLE
- -- Table header
- label(1, 11, "%s", nil, "Turbine #")
- label(16, 11, "%s", nil, "Speed")
- label(32, 11, "%s", nil, "Steam In")
- label(48, 11, "%s", nil, "RF Out")
- label(64, 11, "%s", nil, "Stored RF")
- if w > 80 then
- label(80, 11, "%s", nil, "Coil State")
- end
- hLine(12)
- -- Table body
- -- Update turbine status
- local turbineTotalSteamIn = 0
- turbineMaxSteamIn = 0
- local turbineTotalRFOut = 0
- local turbineStoredRF = 0
- -- by default, only 6 turbines will fit on the screen
- local maxTurbines = 0
- if h > 25 then
- maxTurbines = math.min(#turbine, 28)
- hOffset = 6
- else
- maxTurbines = math.min(#turbine, 6)
- hOffset = 4
- end
- if #turbine > maxTurbines then
- label(1, h - (hOffset + 2), "...", colors.orange)
- label(16, h - (hOffset + 2), "%d %s", colors.orange, (#turbine - 6), "turbine(s) not shown. Totals shown for all turbines.")
- end
- for i = 1, #turbine do
- turbineTotalSteamIn = turbineTotalSteamIn + turbine[i].getFluidFlowRate()
- turbineMaxSteamIn = turbineMaxSteamIn + turbine[i].getFluidFlowRateMax()
- turbineTotalRFOut = turbineTotalRFOut + turbine[i].getEnergyProducedLastTick()
- turbineStoredRF = turbineStoredRF + turbine[i].getEnergyStored()
- -- Auto Mode (TM but not really) fun
- if turbineAutoMode == 900 or turbineAutoMode == 1800 then
- if turbineAutoMode == 900 and turbine[i].getRotorSpeed() < 895 or
- turbineAutoMode == 1800 and turbine[i].getRotorSpeed() < 1795 then
- turbine[i].setInductorEngaged(false)
- else
- turbine[i].setInductorEngaged(true)
- end
- if turbineAutoMode == 900 and turbine[i].getRotorSpeed() > 920 or
- turbineAutoMode == 1800 and turbine[i].getRotorSpeed() > 1820 then
- turbine[i].setActive(false)
- else
- turbine[i].setActive(true)
- end
- end
- if w > 80 then
- label(80, 11, "%s", nil, "Coil State")
- label(96, 11, "%s", nil, "Status")
- end
- end
- for i = 1, maxTurbines do
- label(1, 12 + i, "%d", nil, i)
- if turbine[i].getRotorSpeed() >= 895 and turbine[i].getRotorSpeed() <= 905 or
- turbine[i].getRotorSpeed() >= 1795 and turbine[i].getRotorSpeed() <= 1805 then
- label(16, 12 + i, "%.1f RPM", colors.cyan, turbine[i].getRotorSpeed())
- elseif turbine[i].getRotorSpeed() >= 880 and turbine[i].getRotorSpeed() <= 920 or
- turbine[i].getRotorSpeed() >= 1780 and turbine[i].getRotorSpeed() <= 1820 then
- label(16, 12 + i, "%.1f RPM", colors.lime, turbine[i].getRotorSpeed())
- elseif turbine[i].getRotorSpeed() >= 1821 then
- label(16, 12 + i, "%.1f RPM [!]", colors.red, turbine[i].getRotorSpeed())
- else
- label(16, 12 + i, "%.1f RPM", colors.orange, turbine[i].getRotorSpeed())
- end
- label(32, 12 + i, "%d mB/t", nil, turbine[i].getFluidFlowRate())
- label(48, 12 + i, "%d RF/t", nil, turbine[i].getEnergyProducedLastTick())
- label(64, 12 + i, "%d RF", nil, turbine[i].getEnergyStored())
- if w > 80 then
- if turbine[i].getInductorEngaged() then
- label(80, 12 + i, "%s", colors.lime, "Engaged")
- else
- label(80, 12 + i, "%s", colors.red, "Disengaged")
- end
- if turbine[i].getRotorSpeed() >= 1821 then
- label(96, 12 + i, "%s", colors.red, "Overspeed")
- elseif turbine[i].getRotorSpeed() < 880 then
- label(96, 12 + i, "%s", colors.red, "Underspeed")
- elseif turbine[i].getActive() == false then
- label(96, 12 + i, "%s", colors.gray, "Disabled")
- else
- label(96, 12 + i, "%s", nil, "Normal")
- end
- end
- end
- hLine(h - (hOffset + 1))
- label(1, h - (hOffset), "%s", nil, "TOTAL")
- label(16, h - (hOffset), "%s", nil, "--")
- label(32, h - (hOffset), "%d mB/t", nil, turbineTotalSteamIn)
- label(48, h - (hOffset), "%d RF/t", nil, turbineTotalRFOut)
- label(64, h - (hOffset), "%d RF", nil, turbineStoredRF)
- if turbineAutoMode == 0 then
- label(80, h - (hOffset), "%s %s", nil, "Auto Mode:", "Off")
- elseif turbineAutoMode == 900 then
- label(80, h - (hOffset), "%s %s", nil, "Auto Mode:", "900 RPM")
- elseif turbineAutoMode == 1800 then
- label(80, h - (hOffset), "%s %s", nil, "Auto Mode:", "1800 RPM")
- end
- else
- label(1, 11, "%s: %d RF", nil, reactorStatus.storedRF[1], reactorStatus.storedRF[2])
- label(1, 13, "%s", nil, "No turbines were detected.")
- end
- os.sleep(pollRate)
- elseif currentPage == 2 then
- local maxBarLength = (w - 11) - 11
- box(h - 2, "Press [←] to go to page 1", nil)
- label(1, 11, "%s", nil, "Control Rods")
- hLine(12)
- gpu.fill(11, 13, math.ceil(maxBarLength * (totalControlRodLevel / 100) + 0.5), 1, "=")
- label(1, 13, "%s", nil, "ALL RODS [")
- label(w - 10, 13, "%s %d%%", nil, "]", totalControlRodLevel)
- printControlHelp()
- os.sleep(pollRate)
- end
- else
- printNoSignal()
- end
- end
- -- Unregister key_down event on program exit or things get... weird...
- event.ignore("key_down", onKeyDown)
- term.clear()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement