-
-
Save InternetUnexplorer/ea13f1713d325b914126bcfb9b35e6fd to your computer and use it in GitHub Desktop.
local state, data, reactor, turbine, info_window, rules_window | |
local STATES = { | |
READY = 1, -- Reactor is off and can be started with the lever | |
RUNNING = 2, -- Reactor is running and all rules are met | |
ESTOP = 3, -- Reactor is stopped due to rule(s) being violated | |
UNKNOWN = 4, -- Reactor or turbine peripherals are missing | |
} | |
------------------------------------------------ | |
local rules = {} | |
local function add_rule(name, fn) | |
table.insert(rules, function() | |
local ok, rule_met, value = pcall(fn) | |
if ok then | |
return rule_met, string.format("%s (%s)", name, value) | |
else | |
return false, name | |
end | |
end) | |
end | |
add_rule("REACTOR TEMPERATURE <= 745K", function() | |
local value = string.format("%3dK", math.ceil(data.reactor_temp)) | |
return data.reactor_temp <= 745, value | |
end) | |
add_rule("REACTOR DAMAGE <= 10%", function() | |
local value = string.format("%3d%%", math.ceil(data.reactor_damage * 100)) | |
return data.reactor_damage <= 0.10, value | |
end) | |
add_rule("REACTOR COOLANT LEVEL >= 95%", function() | |
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100)) | |
return data.reactor_coolant >= 0.95, value | |
end) | |
add_rule("REACTOR WASTE LEVEL <= 90%", function() | |
local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100)) | |
return data.reactor_waste <= 0.90, value | |
end) | |
add_rule("TURBINE ENERGY LEVEL <= 95%", function() | |
local value = string.format("%3d%%", math.ceil(data.turbine_energy * 100)) | |
return data.turbine_energy <= 0.95, value | |
end) | |
local function all_rules_met() | |
for i, rule in ipairs(rules) do | |
if not rule() then | |
return false | |
end | |
end | |
-- Allow manual emergency stop with SCRAM button | |
return state ~= STATES.RUNNING or data.reactor_on | |
end | |
------------------------------------------------ | |
local function update_data() | |
data = { | |
lever_on = redstone.getInput("top"), | |
reactor_on = reactor.getStatus(), | |
reactor_burn_rate = reactor.getBurnRate(), | |
reactor_max_burn_rate = reactor.getMaxBurnRate(), | |
reactor_temp = reactor.getTemperature(), | |
reactor_damage = reactor.getDamagePercent(), | |
reactor_coolant = reactor.getCoolantFilledPercentage(), | |
reactor_waste = reactor.getWasteFilledPercentage(), | |
turbine_energy = turbine.getEnergyFilledPercentage(), | |
} | |
end | |
------------------------------------------------ | |
local function colored(text, fg, bg) | |
term.setTextColor(fg or colors.white) | |
term.setBackgroundColor(bg or colors.black) | |
term.write(text) | |
end | |
local function make_section(name, x, y, w, h) | |
for row = 1, h do | |
term.setCursorPos(x, y + row - 1) | |
local char = (row == 1 or row == h) and "\127" or " " | |
colored("\127" .. string.rep(char, w - 2) .. "\127", colors.gray) | |
end | |
term.setCursorPos(x + 2, y) | |
colored(" " .. name .. " ") | |
return window.create(term.current(), x + 2, y + 2, w - 4, h - 4) | |
end | |
local function update_info() | |
local prev_term = term.redirect(info_window) | |
term.clear() | |
term.setCursorPos(1, 1) | |
if state == STATES.UNKNOWN then | |
colored("ERROR RETRIEVING DATA", colors.red) | |
return | |
end | |
colored("REACTOR: ") | |
colored(data.reactor_on and "ON " or "OFF", data.reactor_on and colors.green or colors.red) | |
colored(" LEVER: ") | |
colored(data.lever_on and "ON " or "OFF", data.lever_on and colors.green or colors.red) | |
colored(" R. LIMIT: ") | |
colored(string.format("%4.1f", data.reactor_burn_rate), colors.blue) | |
colored("/", colors.lightGray) | |
colored(string.format("%4.1f", data.reactor_max_burn_rate), colors.blue) | |
term.setCursorPos(1, 3) | |
colored("STATUS: ") | |
if state == STATES.READY then | |
colored("READY, flip lever to start", colors.blue) | |
elseif state == STATES.RUNNING then | |
colored("RUNNING, flip lever to stop", colors.green) | |
elseif state == STATES.ESTOP and not all_rules_met() then | |
colored("EMERGENCY STOP, safety rules violated", colors.red) | |
elseif state == STATES.ESTOP then | |
colored("EMERGENCY STOP, toggle lever to reset", colors.red) | |
end -- STATES.UNKNOWN cases handled above | |
term.redirect(prev_term) | |
end | |
local estop_reasons = {} | |
local function update_rules() | |
local prev_term = term.redirect(rules_window) | |
term.clear() | |
if state ~= STATES.ESTOP then | |
estop_reasons = {} | |
end | |
for i, rule in ipairs(rules) do | |
local ok, text = rule() | |
term.setCursorPos(1, i) | |
if ok and not estop_reasons[i] then | |
colored("[ OK ] ", colors.green) | |
colored(text, colors.lightGray) | |
else | |
colored("[ FAIL ] ", colors.red) | |
colored(text, colors.red) | |
estop_reasons[i] = true | |
end | |
end | |
term.redirect(prev_term) | |
end | |
------------------------------------------------ | |
local function main_loop() | |
-- Search for peripherals again if one or both are missing | |
if not state or state == STATES.UNKNOWN then | |
reactor = peripheral.find("fissionReactorLogicAdapter") | |
turbine = peripheral.find("turbineValve") | |
end | |
if not pcall(update_data) then | |
-- Error getting data (either reactor or turbine is nil?) | |
data = {} | |
state = STATES.UNKNOWN | |
elseif data.reactor_on == nil then | |
-- Reactor is not connected | |
state = STATES.UNKNOWN | |
elseif data.turbine_energy == nil then | |
-- Turbine is not connected | |
state = STATES.UNKNOWN | |
elseif not state then | |
-- Program just started, get current state from lever | |
state = data.lever_on and STATES.RUNNING or STATES.READY | |
elseif state == STATES.READY and data.lever_on then | |
-- READY -> RUNNING | |
state = STATES.RUNNING | |
-- Activate reactor | |
pcall(reactor.activate) | |
data.reactor_on = true | |
elseif state == STATES.RUNNING and not data.lever_on then | |
-- RUNNING -> READY | |
state = STATES.READY | |
elseif state == STATES.ESTOP and not data.lever_on then | |
-- ESTOP -> READY | |
state = STATES.READY | |
elseif state == STATES.UNKNOWN then | |
-- UNKNOWN -> ESTOP | |
state = data.lever_on and STATES.ESTOP or STATES.READY | |
estop_reasons = {} | |
end | |
-- Always enter ESTOP if safety rules are not met | |
if state ~= STATES.UNKNOWN and not all_rules_met() then | |
state = STATES.ESTOP | |
end | |
-- SCRAM reactor if not running | |
if state ~= STATES.RUNNING and reactor then | |
pcall(reactor.scram) | |
end | |
-- Update info and rules windows | |
pcall(update_info) | |
pcall(update_rules) | |
sleep() -- Other calls should already yield, this is just in case | |
return main_loop() | |
end | |
term.setPaletteColor(colors.black, 0x000000) | |
term.setPaletteColor(colors.gray, 0x343434) | |
term.setPaletteColor(colors.lightGray, 0xababab) | |
term.setPaletteColor(colors.red, 0xdb2d20) | |
term.setPaletteColor(colors.green, 0x01a252) | |
term.setPaletteColor(colors.blue, 0x01a0e4) | |
term.clear() | |
local width = term.getSize() | |
info_window = make_section("INFORMATION", 2, 2, width - 2, 7) | |
rules_window = make_section("SAFETY RULES", 2, 10, width - 2, 9) | |
parallel.waitForAny(main_loop, function() | |
os.pullEventRaw("terminate") | |
end) | |
os.reboot() |
Hey, this might be a stupid question but how do i need to connect the computer to the reactor and what should the mode of the redstone logic adapter be?
i tried it with a modem to the logic adapter and every mode possible on the logic adapter. I also tried just sticking the computer directly to the logic adapter but nothing worked. im a bit lost here.
It always says failed to retrive data.
thanks in advance.
Edit:
Nvmd i figured it out. I forgot to connect the turbine.
Hey this code is exactly what I was looking for. Do you know if there is a way to have the display scale to any size?
@Kekalicious Hi! So, unfortunately I wrote this in a hurry and designed the UI around one specific size (built-in screen of an advanced computer) since it's easier to make everything look nice for a fixed size.
That said, it shouldn't be too hard to change; it's not a very complicated program, and so it should be easy to tweak it as needed to fit your situation. :)
@GeilesLuder connect the turbine to what?
I am also having some issues with the connection.
@GeilesLuder connect the turbine to what? I am also having some issues with the connection.
Hey, you also need to connect the turbine to the computer(via modem, same as the reactor itself). I forgot that initially.
how do i use rednet with this instead of wired routers?
@Derrick355 Yes, you can replace
reactor_max_burn_rate
with a constant (in mB/t) if you want a manual cap.The function is
math.min(math.max(0.0, 1 - (data.turbine_energy - A) / B), 1.0)
, where:A
is the lower limit (currently0.5 = 50%
), andA + B
is the upper limit (currently0.5 + 0.25 = 0.75 = 75%
).