SemlerPDX icon

Minecraft ComputerCraft Reactor Control

SemlerPDX | PRO | 08/28/21 08:50:32 PM UTC (Edited) | 0 ⭐ | 4024 👁️ | Never ⏰ | []
Lua |

8.03 KB

|

None

|

0 👍

/

0 👎

--Mekanism Fission Reactor Control w/Remote Emergency Monitor
--v0.92 by SemlerPDX Aug21-26 2021
 
--Reactor Control & Monitor Scripts
-- Control PC (this script): https://pastebin.com/2VrXwGNH
--  and
-- Emergency Monitor PC:  https://pastebin.com/uxE2jE2B
--  and
-- Remote Status Monitor PC: https://pastebin.com/59EWW86J
--
-- example image of setup:  https://imgur.com/a/nrKeBcH
 
--Redstone I/O Sides
battery = "left"
reactor = "right"
monitoring = "top"
--Peripheral Sides
monitorSide = "bottom"
modemSide = "back"
 
--Battery Monitor Redstone Min/Max Levels (0-15)
minBank = 7
maxBank = 15
 
--id of rednet protocols
protocol = "PowerSys" 
protocolCMD = "PowerCMD"
 
controlPC = 20 --id of (this) reactor control PC
remotePC = 21 --id of remote display status monitor PC
hazardPC = 22 --id of critical shutdown monitor PC
 
--Remote Command Keywords
msgConfirmed = "copycopy"
msgDenied = "samestate"
faultClear = "FaultCleared"
clearFaults = "ClearFault"
commandClear = "enable"
commandON = "on"
commandOFF = "off"
--Remote Command Receive Timeout (in seconds)
timeout = 5
 
--Array of Redstone (0-15) into % of 100 for Text Display
batteryLevels = {7,13,20,27,33,40,47,53,60,67,73,80,87,93,100}
 
--Init
y = 1
online = false
reacting = false
shutdownReason = "unknown"
redstone.setOutput(reactor,false)
redstone.setOutput(monitoring,false)
monitor = peripheral.wrap(monitorSide)
modem = peripheral.wrap(modemSide)
rednet.open(modemSide)
 
--Remote Reactor Status Monitor Send Function
local function fStatusUpdate(msg)
  rednet.send(remotePC,msg,protocol)
end
 
--Refresh/Clear Display(s) Function
local function fSet(remoteClear)
  y = 1
  term.clear()
  monitor.clear()
  term.setCursorPos(1,1)
  monitor.setCursorPos(1,1)
  if remoteClear then
    fStatusUpdate("clear")
  end
end
 
--Direct Monitor Screen Write Function
local function fDisplay(txt)
  monitor.write(txt)
  monitor.setCursorPos(1,y)
end
 
--Combined Term/Monitor/Remote Write Function
local function fWrite(msg,display,send)
  y = y + 1
  term.write(msg)
  term.setCursorPos(1,y)
  if display then
    fDisplay(msg)
  end
  if send then
    fStatusUpdate(msg)
  end
end
 
--Change Redstone Input (0-15) into Percentage for Text Display
local function fBankStatus(cellLevel)
  bankCapacity = "Bank Capacity < 7%"
  if cellLevel == 1 then
    bankCapacity = "Bank Capacity > "..batteryLevels[cellLevel].."%"
  elseif cellLevel >= 2 and cellLevel <= 14 then
    bankCapacity = "Bank Capacity >"..batteryLevels[cellLevel].."%"
  else
    bankCapacity = "Bank Capacity 100%"
  end
  return bankCapacity
end
 
--Acknowledge Emergency Shutdown Fault and Get Reason from Monitoring PC
local function fAcknowledge()
  shutdownReason = "unknown"
  id,reason = rednet.receive(protocol)
  rednet.send(id,msgConfirmed,protocol)
  if reason ~= nil then
    shutdownReason = reason
  end
end
 
 
--MAIN LOOP
while true do
  
  --Emergency Shutdown Monitor Function
  local function fShutdown()
    local criticalShutdown = redstone.getInput(monitoring)
    while true do
      sleep(0.05)
      criticalShutdown = redstone.getInput(monitoring)
      if criticalShutdown then
        redstone.setOutput(reactor,false)
        criticalShutdown = nil
        return true
      end
    end
  end
  
  --Master Online State & Battery Monitor Function
  local function fBatteryMonitor()
    while true do
      sleep(5)
      fSet(true)
      currBank = redstone.getAnalogInput(battery)
      reacting = redstone.getOutput(reactor)
      currStatus = fBankStatus(currBank)
      fWrite(currStatus,true,true)
      if currBank == maxBank and reacting then
        fWrite("Bank at capacity",true,true)
        fWrite("Shutting down...",true,true)
        redstone.setOutput(monitoring,false)
        redstone.setOutput(reactor,false)
        sleep(10)
      elseif currBank <= minBank and not reacting and online then
        fWrite("Bank below min",true,true)
        fWrite("Enabling reaction",true,true)
        redstone.setOutput(monitoring,true)
        sleep(5)
        redstone.setOutput(reactor,true)
      elseif currBank >= minBank and not reacting and online then
        fWrite("Bank at capacity",true,true)
        fWrite("Reactor in standby",true,true)
      elseif reacting and not online then
        fWrite("Command Offline",true,true)
        fWrite("Shutting down...",true,true)
        redstone.setOutput(monitoring,false)
        redstone.setOutput(reactor,false)
        sleep(10)
      elseif not reacting and not online then
        fWrite("Systems Offline",true,true)
        fWrite("Reactor in standby",true,true)
      else
        fWrite("Systems Online",true,true)
        if reacting then
          fWrite("Reactor operating",true,true)
        else
          fWrite("Reactor in standby",true,true)
        end
      end
      monitor.setCursorPos(1,5)
      if online then
        fDisplay(" -Tap to Disable- ")
        fStatusUpdate(commandON)
      else
        fDisplay(" -Tap to Enable- ")
        fStatusUpdate(commandOFF)
      end
    end
  end
  
  --Touchscreen Systems Online Toggle
  local function fTouch()
    while true do
      sleep(3)
      event,side,xPos,yPos = os.pullEvent("monitor_touch")
      if not online then
        online = true
      elseif online then
        online = false
      end
    end
  end  
  
  --Rednet Systems Online Toggle
  local function fListen()
    while true do
      id,message = rednet.receive(protocolCMD)
      rednet.send(id,msgConfirmed,protocolCMD)
      id,message = rednet.receive(protocolCMD,timeout)
      if message ~= nil then
        if message == commandON and not online then
          online = true
          rednet.send(id,msgConfirmed,protocolCMD)
        elseif message == commandOFF and online then
          online = false
          rednet.send(id,msgConfirmed,protocolCMD)
        else
          rednet.send(id,msgDenied,protocolCMD)
        end
      end
    end
  end
  
  --Emergency Shutdown Fault Acknowledgment
  local function fClearFault()
    while true do
      sleep(5)
      local faultsActive  = redstone.getInput(monitoring)
      if not faultsActive then
        faultsActive = nil
        return true
      end
    end
  end
  
  --Fault Clear Terminal Input Confirmation Function
  local function fConfirmCleared()
    while true do
      fSet(true)
      currBank = redstone.getAnalogInput(battery)
      currStatus = fBankStatus(currBank)
      fWrite(currStatus,true,true)
      fWrite("Critical "..shutdownReason.."!",true,true)
      fWrite("EMERGENCY SHUTDOWN",true,true)
      fWrite("Clear faults, then type 'enable' and press Enter")
      term.write("> ")
      local confirmCleared = read()
      fSet()
      if confirmCleared == commandClear then
        fWrite("Confirming Cleared")
        rednet.send(hazardPC,faultClear,protocol)
        id,message = rednet.receive(protocol,15)
        if message == faultCleared then
          sleep(5)
        end
        faultsActive = redstone.getInput(monitoring)
        fSet()
        if not faultsActive then
          fWrite("Clear Confirmed")
          fWrite("Zero Faults Detected")
          fWrite("Enabling Operations")
          return true
        else
          fWrite("Clear Disregarded")
          fWrite("Reactor Faults Detected!")
          fWrite("Cannot Enable Operations!")
        end
      else
        fWrite("Invalid Command...")
        fWrite("Reactor Faults Detected!")
        fWrite("Clear faults and enter 'enable'")
      end
      sleep(4)
    end
  end
  
  
  --MAIN Reactor Function monitoring battery, cmd input, and shutdown signal
  reactorFunction = parallel.waitForAny(fShutdown,fBatteryMonitor,fTouch,fListen)
  
  --Emergency Shutdown, output to screens/rednet
  if reactorFunction == 1 then
    redstone.setOutput(monitoring,false)
    fAcknowledge()
    --Force Terminal Input that faults cleared
    faultAcknowledged = parallel.waitForAll(fClearFault,fConfirmCleared)
  end
  
end

Comments