local reactor = peripheral.wrap("BigReactors-Reactor_0") local monitor = peripheral.wrap("monitor_0") rednet.open("top") controllers = {} controllers[1] = true -- Allow computer ID#1 to access reactor control local target_power = 5000 -- RF/Tick local control_rod_level = 50 function clamp(val, min, max) if val > max then return max elseif val < min then return min else return val end end function drawBar(x, y, size, perc) local bgColor = monitor.getBackgroundColor() local ox, oy = monitor.getCursorPos() monitor.setCursorPos(x, y) monitor.setBackgroundColor(colors.green) local percGreen = clamp(math.floor(perc * size), 0, size) local percGray = clamp(size - percGreen, 0, size - percGreen) if percGray < 0 then percGray = 0 end for i = percGreen,1,-1 do monitor.write(" ") end monitor.setBackgroundColor(colors.lightGray) for i = percGray,1,-1 do monitor.write(" ") end monitor.setBackgroundColor(bgColor) monitor.setCursorPos(ox, oy) end function getControlRodDiff(RFDiff) if RFDiff > 10000 then return 5 elseif RFDiff > 5000 then return 3 elseif RFDiff > 1000 then return 1 elseif RFDiff > 500 then return 0.5 elseif RFDiff > 100 then return 0.1 else return 0.05 end end function formatRF(rf) if rf >= 1000000 then return round(rf/1000000, 2) .. " MiRF" elseif rf >= 1000 then return round(rf/1000, 2) .. " KiRF" else return math.floor(rf) .. " RF" end end function round(num, numDecimalPlaces) local mult = 10^(numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end function drawBoxWithCenteredText(x,y,w,h,text,color) local ox,oy = monitor.getCursorPos() local bgColor = monitor.getBackgroundColor() monitor.setBackgroundColor(color) for cy=1,h,1 do for cx=1,w,1 do monitor.setCursorPos(x+cx,y+cy) monitor.write(" ") end end local cx = math.floor(w / 2 + x - string.len(text) / 2 + 1) local cy = math.floor(h / 2 + y + 1) monitor.setCursorPos(cx, cy) monitor.write(text) monitor.setBackgroundColor(bgColor) monitor.setCursorPos(ox, oy) end monitor.setBackgroundColor(colors.black) monitor.clear() local mw, mh = monitor.getSize() local reactor_enabled = false local buttons = {} function renderButtons() for i = 1, #buttons do local button = buttons[i] if not reactor_enabled then if button.drod then drawBoxWithCenteredText(button.x,button.y,button.w,button.h,button.text,button.color) end else drawBoxWithCenteredText(button.x,button.y,button.w,button.h,button.text,button.color) end end end function inBounds(n, min, max) return n <= max and n >= min end function addButton(x,y,w,h,text,color,doRenderOnDisable, executor) local button = { x = x, y = y, w = w, h = h, text = text, color = color, drod = doRenderOnDisable, executor = executor } buttons[#buttons+1] = button end function startReactor(btn) monitor.clear() reactor_enabled = true end function stopReactor(btn) monitor.clear() reactor_enabled = false end function changeTargetPower(btn) local num = btn.text:sub(2) num = tonumber(num) if btn.color == colours.red then num = num * -1 end target_power = target_power + num end addButton(2,mh - 8,15,5,"SHUT DOWN",colours.red, true, stopReactor) addButton(19,mh - 8,15,5,"START",colours.green, true, startReactor) addButton(2, 9, 7, 3, "-10", colours.red, false, changeTargetPower) addButton(11, 9, 7, 3, "-100", colours.red, false, changeTargetPower) addButton(20, 9, 7, 3, "-1000", colours.red, false, changeTargetPower) addButton(29, 9, 7, 3, "+1000", colours.green, false, changeTargetPower) addButton(38, 9, 7, 3, "+100", colours.green, false, changeTargetPower) addButton(47, 9, 7, 3, "+10", colours.green, false, changeTargetPower) local cur_power_gen = 0 function controlReactor() while true do cur_power_gen = reactor.getEnergyProducedLastTick() reactor.setActive(reactor_enabled) if cur_power_gen ~= 0 and reactor_enabled then local diff = getControlRodDiff(math.abs(cur_power_gen - target_power)) if cur_power_gen > target_power then control_rod_level = clamp(control_rod_level + diff, 0, 100) elseif cur_power_gen < target_power then control_rod_level = clamp(control_rod_level - diff, 0, 100) end reactor.setAllControlRodLevels(control_rod_level) monitor.setCursorPos(2,2) monitor.write("Control Rod Level: ") drawBar(22,2,40,control_rod_level/100) monitor.setCursorPos(22,3) monitor.write(math.floor(control_rod_level) .. "\% ") monitor.setCursorPos(2,5) monitor.write("Power Generation: ") drawBar(22,5,40,cur_power_gen/target_power) monitor.setCursorPos(22,6) monitor.write(formatRF(cur_power_gen) .. "/t ") monitor.setCursorPos(2,8) monitor.write("Target power generation: " .. formatRF(target_power) .. "/t") end if not reactor_enabled then monitor.setCursorPos(2,2) monitor.write("Reactor is offline") end renderButtons() sleep(0.1) end end function pullEvents() while true do event, side, x, y = os.pullEvent("monitor_touch") for i=1, #buttons do local button = buttons[i] if inBounds(x, button.x, button.x + button.w) and inBounds(y, button.y, button.y + button.h) then button.executor(button) break end end end end function waitForRednetCommand() while true do local senderId, command, protocol = rednet.receive("reactor_control") command = textutils.unserialize(command) if controllers[senderId] ~= nil and controllers[senderId] then print("Received rednet command from " .. senderId) print(command) local reactorStatus = { control_rod_level = control_rod_level, cur_power_gen = cur_power_gen, target_power = target_power, reactor_enabled = reactor_enabled, command_executed = false } for i=1, #buttons do local button = buttons[i] if command.button == button.text then button.executor(button) reactorStatus.command_executed = true break end end rednet.send(senderId, textutils.serialize(reactorStatus), "reactor_response") end end end parallel.waitForAny(pullEvents, controlReactor, waitForRednetCommand)