Advertisement
Guest User

Untitled

a guest
Jan 13th, 2024
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.64 KB | None | 0 0
  1. ---------------------------------------------------
  2. -- Mekanism Fission Reactor Monitoring Program   --
  3. -- Created for CC:Tweaked and Mekanism           --
  4. -- Originally created by InternetUnexplorer on   --
  5. -- GitHub. Modified for personal use, by         --
  6. -- iPlay_G on Minecraft, Derrick355 on GitHub.   --
  7. -- As the original program did not contain any   --
  8. -- license, this will not contain any license.   --
  9. -- However, this software is provided "AS-IS",   --
  10. -- with NO WARRANTY of ANY kind. There is no     --
  11. -- guarentee of fitness for a particular         --
  12. -- purpose.                                      --
  13. -- Feel free to use it, but I, nor the           --
  14. -- original author are responsible for any       --
  15. -- issues arising from the use of this program.  --
  16. --                    -=@=-                      --
  17. -- Thank you for downloading this program.       --
  18. ---------------------------------------------------
  19.  
  20.  
  21. --- NOTES ---
  22. -- If you see 'CRITICAL' on your monitor as the
  23. -- state, that is OK. Critical is what real
  24. -- reactors are considered when operating normally.
  25.  
  26. -- It is generally recommended to edit settings
  27. -- in an IDE or text editor for ease of use.
  28.  
  29. -- It is assumed you have a 6 wide, 4 tall monitor
  30. -- attached via a modem.
  31.  
  32. -- References to an analog lever are common, since
  33. -- I used the Create mod, however if you don't
  34. -- have it, any way to input a variable-power
  35. -- redstone signal should work.
  36.  
  37. -- Binary levers are just vanillia levers.
  38.  
  39.  
  40. --- RECOMMENDED & ASSUMED COMPUTER I/O SETUP ---
  41. -- TOP: Binary lever, used to enable/disable manual burn rate control
  42. -- LEFT: Analog lever, used as coarse adjust on burn control
  43. -- RIGHT: Analog lever, used as fine adjust on burn control
  44. -- BOTTOM: Binary lever, used as reactor on/off control
  45. -- BACK: Modem to connect to reactor, turbine, and monitor
  46. -- FRONT: Alarm or siren. Outputs a redstone signal if turbine power falls below a set threshold.
  47.  
  48.  
  49. --- VARIABLE SETTINGS ---
  50. -- Set the multiplier for the burn rate coarse setting.
  51. -- Default = 75
  52. burn_rate_coarse_multi = 75
  53.  
  54. -- Set the multiplier for the burn rate fine setting.
  55. -- Default = 5
  56. burn_rate_fine_multi = 5
  57.  
  58. -- Maximum auto burn rate to establish
  59. -- Default = 120
  60. burn_rate_auto_max = 120
  61.  
  62. -- What turbine power percent value should burn rate be max at?
  63. -- For this value and all lower, burn rate will be at the max defined above.
  64. -- Default = 0.5 (for 50%)
  65. min_turbine_power = 0.50
  66.  
  67. -- What turbine power percent value should burn rate be zero at?
  68. -- For this value and all higher, burn rate will be at zero.
  69. -- Default = 0.75 (for 75%)
  70. max_turbine_power = 0.75
  71.  
  72. -- What value should the alarm go off if turbine power falls below?
  73. -- Default = 0.46
  74. turbine_min_power = 0.46
  75.  
  76. -- What is the monitor called on the network?
  77. -- Default = monitor_0
  78. monitor_name = "monitor_2"
  79.  
  80. -- Do not modify anything past this line unless you know what you are doing.
  81.  
  82. ------------------------------------------------
  83.  
  84. local state, data, reactor, turbine, info_window, rules_window
  85.  
  86. local STATES = {
  87.     READY = 1, -- Reactor is off and can be started with the lever
  88.     RUNNING = 2, -- Reactor is running and all rules are met
  89.     ESTOP = 3, -- Reactor is stopped due to rule(s) being violated
  90.     UNKNOWN = 4, -- Reactor or turbine peripherals are missing
  91. }
  92.  
  93. ------------------------------------------------
  94.  
  95. incoming_restart = false
  96.  
  97. local rules = {}
  98.  
  99. local function add_rule(name, fn)
  100.     table.insert(rules, function()
  101.         local ok, rule_met, value = pcall(fn)
  102.         if ok then
  103.             return rule_met, string.format("%s (%s)", name, value)
  104.         else
  105.             return false, name
  106.         end
  107.     end)
  108. end
  109.  
  110. add_rule("REACTOR TEMPERATURE      <=  1100K  ", function()
  111.     local value = string.format("%3dK", math.ceil(data.reactor_temp))
  112.     return data.reactor_temp <= 1100, value
  113. end)
  114.  
  115. add_rule("REACTOR DAMAGE           <=    10%  ", function()
  116.     local value = string.format("%3d%%", math.ceil(data.reactor_damage * 100))
  117.     return data.reactor_damage <= 0.10, value
  118. end)
  119.  
  120. add_rule("REACTOR COOLANT LEVEL    >=    95%  ", function()
  121.     local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
  122.     return data.reactor_coolant >= 0.95, value
  123. end)
  124.  
  125. add_rule("REACTOR WASTE LEVEL      <=    90%  ", function()
  126.     local value = string.format("%3d%%", math.ceil(data.reactor_waste * 100))
  127.     return data.reactor_waste <= 0.90, value
  128. end)
  129.  
  130. add_rule("TURBINE ENERGY LEVEL     <=    95%  ", function()
  131.     local value = string.format("%3d%%", math.ceil(data.turbine_energy * 100))
  132.     return data.turbine_energy <= 0.95, value
  133. end)
  134.  
  135. add_rule("INCOMING SERVER RESTART  ==  FALSE  ", function()
  136.     return incoming_restart, incoming_restart
  137. end)
  138.  
  139. local function all_rules_met()
  140.     for i, rule in ipairs(rules) do
  141.         if not rule() then
  142.             return false
  143.         end
  144.     end
  145.     -- Allow manual emergency stop with SCRAM button
  146.     return state ~= STATES.RUNNING or data.reactor_on
  147. end
  148.  
  149. ------------------------------------------------
  150.  
  151. local function update_data()
  152.     coarse_adjust = (tonumber(redstone.getAnalogInput("left")) * burn_rate_coarse_multi)
  153.     fine_adjust = (tonumber(redstone.getAnalogInput("right")) * burn_rate_fine_multi)
  154.     set_burn_rate = (coarse_adjust + fine_adjust)
  155.  
  156.     data = {
  157.         lever_on = redstone.getInput("bottom"),
  158.         burn_rate_limit = set_burn_rate,
  159.         burn_rate_limited = redstone.getInput("top"),
  160.  
  161.         reactor_on = reactor.getStatus(),
  162.         reactor_burn_rate = reactor.getBurnRate(),
  163.         reactor_max_burn_rate = reactor.getMaxBurnRate(),
  164.         reactor_temp = reactor.getTemperature(),
  165.         reactor_damage = reactor.getDamagePercent(),
  166.         reactor_coolant = reactor.getCoolantFilledPercentage(),
  167.         reactor_waste = reactor.getWasteFilledPercentage(),
  168.  
  169.         turbine_energy = turbine.getEnergyFilledPercentage(),
  170.         turbine_power = turbine.getEnergy(),
  171.         turbine_power = turbine.getEnergy(),
  172.         max_turbine_power = turbine.getMaxEnergy()
  173.     }
  174.  
  175. end
  176. ------------------------------------------------
  177.  
  178. local monitor = peripheral.wrap(monitor_name)
  179.  
  180. term.redirect(monitor)
  181.  
  182. local function colored(text, fg, bg)
  183.     term.setTextColor(fg or colors.white)
  184.     term.setBackgroundColor(bg or colors.black)
  185.     term.write(text)
  186. end
  187.  
  188. local function make_section(name, x, y, w, h, color)
  189.     for row = 1, h do
  190.         term.setCursorPos(x, y + row - 1)
  191.         local char = (row == 1 or row == h) and "\127" or " "
  192.         colored("\127" .. string.rep(char, w - 2) .. "\127", color or colors.gray)
  193.     end
  194.  
  195.     term.setCursorPos(x + 2, y)
  196.     colored(" " .. name .. " ")
  197.  
  198.     return window.create(term.current(), x + 2, y + 2, w - 4, h - 4)
  199. end
  200.  
  201. local function update_info()
  202.     local prev_term = term.redirect(info_window)
  203.  
  204.     term.clear()
  205.     term.setCursorPos(1, 1)
  206.  
  207.     if state == STATES.UNKNOWN then
  208.         colored("ERROR RETRIEVING DATA", colors.red)
  209.         return
  210.     end
  211.  
  212.     colored("REACTOR: ")
  213.     colored(data.reactor_on and "CRITICAL" or "SHUTDOWN", data.reactor_on and colors.green or colors.red)
  214.     colored(" LEVER: ")
  215.     colored(data.lever_on and "POWERED" or "SECURED", data.lever_on and colors.green or colors.red)
  216.     colored(" BURN RATE: ")
  217.     if data.burn_rate_limited == false then
  218.         colored(string.format("%4.1f", data.reactor_burn_rate), colors.blue)
  219.     else
  220.         colored(string.format("%4.1f", data.reactor_burn_rate), colors.yellow)
  221.     end
  222.     colored("/", colors.lightGray)
  223.     colored(string.format("%4.0f", data.reactor_max_burn_rate), colors.blue)
  224.  
  225.     term.setCursorPos(34, 2)
  226.     colored("SET LIMIT: ")
  227.     if data.burn_rate_limited then
  228.         colored(string.format("%4.1f", data.burn_rate_limit), colors.green)
  229.     else
  230.         colored(string.format("%4.1f", data.burn_rate_limit), colors.gray)
  231.     end
  232.  
  233.     term.setCursorPos(1, 4)
  234.  
  235.     colored("STATUS: ")
  236.     if state == STATES.READY then
  237.         colored("READY - PULL LEVER TO STARTUP", colors.blue)
  238.     elseif state == STATES.RUNNING then
  239.         colored("RUNNING - PULL LEVER TO SHUTDOWN", colors.green)
  240.     elseif state == STATES.ESTOP and not all_rules_met() then
  241.         colored("SCRAM - SAFETY RULE VIOLATED", colors.red)
  242.     elseif state == STATES.ESTOP then
  243.         colored("SCRAM - TOGGLE LEVER TO RESET", colors.red)
  244.     end -- STATES.UNKNOWN cases handled above
  245.  
  246.     term.setCursorPos(1, 6)
  247.    
  248.     colored("STORED POWER: ")
  249.     colored(string.format("%4.0f", (data.turbine_power*4/1000000)), colors.green)
  250.     colored(" MFE", colors.green)
  251.     colored("/", colors.lightGray)
  252.  
  253.     colored(string.format("%4.0f", (data.max_turbine_power*4/1000000)), colors.blue)
  254.     colored(" MFE", colors.blue)
  255.     colored(" (")
  256.     colored(string.format("%5.2f", (data.turbine_energy*100)), colors.green)
  257.     colored("%", colors.green)
  258.     colored(")")
  259.  
  260.     term.redirect(prev_term)
  261. end
  262.  
  263.  
  264. local estop_reasons = {}
  265.  
  266. local function update_rules()
  267.     local prev_term = term.redirect(rules_window)
  268.  
  269.     term.clear()
  270.  
  271.     if state ~= STATES.ESTOP then
  272.         estop_reasons = {}
  273.     end
  274.  
  275.     for i, rule in ipairs(rules) do
  276.         local ok, text = rule()
  277.         term.setCursorPos(1, i)
  278.         if ok and not estop_reasons[i] then
  279.             colored("[ SAFE ] ", colors.green)
  280.             colored(text, colors.lightGray)
  281.         else
  282.             colored("[ FAIL ] ", colors.red)
  283.             colored(text, colors.red)
  284.             estop_reasons[i] = true
  285.         end
  286.     end
  287.  
  288.     term.redirect(prev_term)
  289. end
  290.  
  291. ------------------------------------------------
  292.  
  293. local function main_loop()
  294.     -- Search for peripherals again if one or both are missing
  295.     if not state or state == STATES.UNKNOWN then
  296.         reactor = peripheral.find("fissionReactorLogicAdapter")
  297.         turbine = peripheral.find("turbineValve")
  298.     end
  299.  
  300.     if not pcall(update_data) then
  301.         -- Error getting data (either reactor or turbine is nil?)
  302.         data = {}
  303.         state = STATES.UNKNOWN
  304.     elseif data.reactor_on == nil then
  305.         -- Reactor is not connected
  306.         state = STATES.UNKNOWN
  307.     elseif data.turbine_energy == nil then
  308.         -- Turbine is not connected
  309.         state = STATES.UNKNOWN
  310.     elseif not state then
  311.         -- Program just started, get current state from lever
  312.         state = data.lever_on and STATES.RUNNING or STATES.READY
  313.     elseif state == STATES.READY and data.lever_on then
  314.         -- READY -> RUNNING
  315.         state = STATES.RUNNING
  316.         -- Activate reactor
  317.         pcall(reactor.activate)
  318.         data.reactor_on = true
  319.     elseif state == STATES.RUNNING and not data.lever_on then
  320.         -- RUNNING -> READY
  321.         state = STATES.READY
  322.     elseif state == STATES.ESTOP and not data.lever_on then
  323.         -- ESTOP -> READY
  324.         state = STATES.READY
  325.     elseif state == STATES.UNKNOWN then
  326.         -- UNKNOWN -> ESTOP
  327.         state = data.lever_on and STATES.ESTOP or STATES.READY
  328.         estop_reasons = {}
  329.     end
  330.  
  331.     -- Always enter ESTOP if safety rules are not met
  332.     if state ~= STATES.UNKNOWN and not all_rules_met() then
  333.         state = STATES.ESTOP
  334.     end
  335.  
  336.     -- SCRAM reactor if not running
  337.     if state ~= STATES.RUNNING and reactor then
  338.         pcall(reactor.scram)
  339.     end
  340.  
  341.     -- Make Windows
  342.     local width = term.getSize()
  343.     if state == STATES.ESTOP then
  344.         window_color = colors.red
  345.     elseif state == STATES.READY then
  346.         window_color = colors.green
  347.     else
  348.         window_color = colors.gray
  349.     end
  350.     info_window = make_section("INFORMATION", 2, 2, width - 2, 10, window_color)
  351.     rules_window = make_section("SAFETY RULES", 2, 13, width - 2, 13, window_color)
  352.  
  353.     -- Update info and rules windows
  354.     pcall(update_info)
  355.     pcall(update_rules)
  356.  
  357.     -- Update max burn rate to keep turbine below 75% energy.
  358.     if state ~= STATES.UNKNOWN and data.burn_rate_limited == false then
  359.    
  360.         local tgt_burn_pct = math.min(math.max(0.0, 1 - (data.turbine_energy - min_turbine_power) / (max_turbine_power - min_turbine_power)), 1.0)
  361.         pcall(reactor.setBurnRate, tgt_burn_pct * burn_rate_auto_max)
  362.     elseif state ~= STATES.UNKNOWN and data.burn_rate_limited == true then
  363.         pcall(reactor.setBurnRate, data.burn_rate_limit) -- Let burn rate be limited by an analog lever
  364.     end
  365.  
  366.     if data.turbine_energy < turbine_min_power then --Sound an alarm that's attached to the front of the computer if turbine power falls below 45%.
  367.         redstone.setOutput("right", true)
  368.     else
  369.         redstone.setOutput("right", false)
  370.     end
  371.     sleep() -- Other calls should already yield, this is just in case
  372.     return main_loop()
  373. end
  374.  
  375. term.setPaletteColor(colors.black, 0x000000)
  376. term.setPaletteColor(colors.gray, 0x343434)
  377. term.setPaletteColor(colors.lightGray, 0xababab)
  378. term.setPaletteColor(colors.red, 0xdb2d20)
  379. term.setPaletteColor(colors.green, 0x01a252)
  380. term.setPaletteColor(colors.blue, 0x01a0e4)
  381. term.clear()
  382.  
  383. local function shutdown_on_restart_warning()
  384.     chatBox = peripheral.find("chatBox")
  385.     local event, username, message, uuid, isHidden = os.pullEvent("chat")
  386.     --print("The 'chat' event was fired with the username " .. username .. " and the message " .. message)
  387.     chatBox.sendMessage("username: " .. username .. "message: ".. message)
  388.     if username == "sayCommand" and message == "SCRAM" then
  389.         incoming_restart = true
  390.         chatBox.sendMessage("SCRAM aye")
  391.     end
  392.  
  393. parallel.waitForAny(main_loop, function()
  394.     os.pullEventRaw("terminate")
  395. end)
  396.  
  397. os.reboot()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement