Compare commits
7 Commits
minecartch
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e29a3a6bc | |||
| 9d3e06ac9f | |||
| 82ba0fde66 | |||
| 819a33adfb | |||
| a0e08089e7 | |||
| 573cbaafbc | |||
| 4a035eb89a |
314
Lua minecraft/6TurbineFuelFi.lua
Normal file
314
Lua minecraft/6TurbineFuelFi.lua
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 1200K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 1200, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
||||||
|
return data.reactor_fuel >= 0.05, 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 1 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 2 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
||||||
|
return data.turbine2_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 3 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine3_energy * 100))
|
||||||
|
return data.turbine3_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 4 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine4_energy * 100))
|
||||||
|
return data.turbine4_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 5 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine5_energy * 100))
|
||||||
|
return data.turbine5_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 6 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine6_energy * 100))
|
||||||
|
return data.turbine6_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(),
|
||||||
|
reactor_fuel = reactor.getFuelFilledPercentage(),
|
||||||
|
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
||||||
|
turbine2_energy = turbine2.getEnergyFilledPercentage(),
|
||||||
|
turbine3_energy = turbine2.getEnergyFilledPercentage(),
|
||||||
|
turbine4_energy = turbine2.getEnergyFilledPercentage(),
|
||||||
|
turbine5_energy = turbine2.getEnergyFilledPercentage(),
|
||||||
|
turbine6_energy = turbine2.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.2f", 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.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_1")
|
||||||
|
turbine2 = peripheral.wrap("turbineValve_2")
|
||||||
|
turbine3 = peripheral.wrap("turbineValve_3")
|
||||||
|
turbine4 = peripheral.wrap("turbineValve_4")
|
||||||
|
turbine5 = peripheral.wrap("turbineValve_5")
|
||||||
|
turbine6 = peripheral.wrap("turbineValve_6")
|
||||||
|
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine2_energy == nil then
|
||||||
|
-- Turbine 2 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine3_energy == nil then
|
||||||
|
-- Turbine 3 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine4_energy == nil then
|
||||||
|
-- Turbine 4 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine5_energy == nil then
|
||||||
|
-- Turbine 5 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine6_energy == nil then
|
||||||
|
-- Turbine 6 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine3_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine4_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine5_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine6_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 24)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
258
Lua minecraft/Fuelfi.lua
Normal file
258
Lua minecraft/Fuelfi.lua
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 1200K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 1200, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
||||||
|
return data.reactor_fuel >= 0.05, 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 1 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_energy <= 0.95, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 2 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
||||||
|
return data.turbine2_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(),
|
||||||
|
reactor_fuel = reactor.getFuelFilledPercentage(),
|
||||||
|
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
||||||
|
turbine2_energy = turbine2.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.2f", 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.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_1")
|
||||||
|
turbine2 = peripheral.wrap("turbineValve_2")
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine2_energy == nil then
|
||||||
|
-- Turbine 2 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 16)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
244
Lua minecraft/Fuelfi2.lua
Normal file
244
Lua minecraft/Fuelfi2.lua
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 1200K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 1200, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 30%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.30, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
||||||
|
return data.reactor_fuel >= 0.05, 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 1 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_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(),
|
||||||
|
reactor_fuel = reactor.getFuelFilledPercentage(),
|
||||||
|
turbine1_energy = turbine1.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.2f", 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.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_1")
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 10)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
244
Lua minecraft/Fuelfi3.lua
Normal file
244
Lua minecraft/Fuelfi3.lua
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 1200K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 1200, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
||||||
|
return data.reactor_fuel >= 0.05, 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 1 ENERGY LEVEL <= 95%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_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(),
|
||||||
|
reactor_fuel = reactor.getFuelFilledPercentage(),
|
||||||
|
turbine1_energy = turbine1.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.2f", 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.wrap("fissionReactorLogicAdapter_0")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_0")
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
shell.run("reboot")
|
||||||
|
end
|
||||||
|
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 16)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
28
Lua minecraft/LiveReactor.lua
Normal file
28
Lua minecraft/LiveReactor.lua
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
--Stable data
|
||||||
|
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
local maxburn= tonumber(p.getMaxBurnRate())
|
||||||
|
local Height= tonumber(p.getHeight())
|
||||||
|
local Length= tonumber(p.getLength())
|
||||||
|
local Width= tonumber(p.getWidth())
|
||||||
|
local WasteCap= tonumber(p.getWasteCapacity())
|
||||||
|
local Coolantcap= tonumber(p.getCoolantCapacity())
|
||||||
|
local FuelCap= tonumber(p.getFuelCapacity())
|
||||||
|
while true do
|
||||||
|
--Live Data
|
||||||
|
local CurrentFuel= tonumber(p.getFuel().amount)
|
||||||
|
local CurrentCoolant= tonumber(p.getCoolant().amount)
|
||||||
|
local CurrentWaste= tonumber(p.getWaste().amount)
|
||||||
|
--Math
|
||||||
|
local TotalFuel= (CurrentFuel/FuelCap)*100
|
||||||
|
TotalFuel = string.format("%4.2f", TotalFuel)
|
||||||
|
local TotalCoolant= (CurrentCoolant/Coolantcap)*100
|
||||||
|
TotalCoolant = string.format("%4.2f", TotalCoolant)
|
||||||
|
local TotalWaste= (CurrentWaste/WasteCap)*100
|
||||||
|
TotalWaste = string.format("%4.2f", TotalWaste)
|
||||||
|
--Screen Clear
|
||||||
|
term.setCursorPos(0,0)
|
||||||
|
term.clear()
|
||||||
|
--Print Data
|
||||||
|
print("Max Burnrate: " .. maxburn .."\nCoolant Capacity: "..Coolantcap.."\nCoolant Percent: "..TotalCoolant.."\nCurrent Coolant: "..CurrentCoolant.."\nFuel Capacity: ".. FuelCap.."\nFuel Percent: "..TotalFuel.."\nCurrent Fuel: "..CurrentFuel.."\nWaste Capacity: "..WasteCap.."\nWaste Percent: "..TotalWaste.."\nCurrent Waste: "..CurrentWaste.."\nHeight: "..Height.."\nLength: "..Length.."\nWidth: "..Width)
|
||||||
|
sleep(1)
|
||||||
|
end
|
||||||
9
Lua minecraft/Reactordata.lua
Normal file
9
Lua minecraft/Reactordata.lua
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
local maxburn= tonumber(p.getMaxBurnRate())
|
||||||
|
local Height= tonumber(p.getHeight())
|
||||||
|
local Length= tonumber(p.getLength())
|
||||||
|
local Width= tonumber(p.getWidth())
|
||||||
|
local WastePercent= tonumber(p.getWasteCapacity())
|
||||||
|
local Coolantcap= tonumber(p.getCoolantCapacity())
|
||||||
|
local FuelCap= tonumber(p.getFuelCapacity())
|
||||||
|
print("Max Burnrate: " .. maxburn .."\nCoolant Capacity: "..Coolantcap.."\nFuel Capacity: ".. FuelCap.."\nWaste Capacity: "..WastePercent.."\nHeight: "..Height.."\nLength: "..Length.."\nWidth: "..Width)
|
||||||
18
Lua minecraft/burnrate.lua
Normal file
18
Lua minecraft/burnrate.lua
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
local p=peripheral.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
local burn = 0
|
||||||
|
local maxburn= tonumber(p.getMaxBurnRate())
|
||||||
|
while true do
|
||||||
|
burn = tonumber(read())
|
||||||
|
if burn > maxburn then
|
||||||
|
print("Burnrate not reachable")
|
||||||
|
else
|
||||||
|
if burn > 100 then
|
||||||
|
print("Burn rate to high")
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
p.setBurnRate(burn)
|
||||||
|
print("Reactor Burnrate =",p.getBurnRate())
|
||||||
252
Lua minecraft/fi.lua
Normal file
252
Lua minecraft/fi.lua
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 5100K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 5100, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 50%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.50, 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 1 ENERGY LEVEL <= 30%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_energy <= 0.30, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
--add_rule("TURBINE 2 ENERGY LEVEL <= 30%", function()
|
||||||
|
--local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
||||||
|
--return data.turbine2_energy <= 0.30, 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(),
|
||||||
|
|
||||||
|
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
||||||
|
--turbine2_energy = turbine2.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.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_1")
|
||||||
|
--turbine2 = peripheral.wrap("turbineValve_2")
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
--elseif data.turbine2_energy == nil then
|
||||||
|
-- Turbine 2 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
reactor.activate()
|
||||||
|
end
|
||||||
|
--if data.turbine2_energy < 0.1 and state == data.lever_on then
|
||||||
|
--reactor.activate()
|
||||||
|
--end
|
||||||
|
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 10)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
257
Lua minecraft/fi2.lua
Normal file
257
Lua minecraft/fi2.lua
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
sleep(0)
|
||||||
|
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 <= 5100K", function()
|
||||||
|
local value = string.format("%3dK", math.ceil(data.reactor_temp))
|
||||||
|
return data.reactor_temp <= 5100, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR DAMAGE <= 10%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.reactor_damage))
|
||||||
|
return data.reactor_damage <= 10, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR COOLANT LEVEL >= 50%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_coolant * 100))
|
||||||
|
return data.reactor_coolant >= 0.50, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("REACTOR FUEL LEVEL >= 5%", function()
|
||||||
|
local value = string.format("%3d%%", math.floor(data.reactor_fuel * 100))
|
||||||
|
return data.reactor_fuel >= 0.05, 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 1 ENERGY LEVEL <= 30%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine1_energy * 100))
|
||||||
|
return data.turbine1_energy <= 0.30, value
|
||||||
|
end)
|
||||||
|
|
||||||
|
add_rule("TURBINE 2 ENERGY LEVEL <= 30%", function()
|
||||||
|
local value = string.format("%3d%%", math.ceil(data.turbine2_energy * 100))
|
||||||
|
return data.turbine2_energy <= 0.30, 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(),
|
||||||
|
reactor_fuel = reactor.getFuelFilledPercentage(),
|
||||||
|
turbine1_energy = turbine1.getEnergyFilledPercentage(),
|
||||||
|
turbine2_energy = turbine2.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 + 3, 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.2f", 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.wrap("fissionReactorLogicAdapter_2")
|
||||||
|
turbine1 = peripheral.wrap("turbineValve_1")
|
||||||
|
turbine2 = peripheral.wrap("turbineValve_2")
|
||||||
|
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.turbine1_energy == nil then
|
||||||
|
-- Turbine 1 is not connected
|
||||||
|
state = STATES.UNKNOWN
|
||||||
|
elseif data.turbine2_energy == nil then
|
||||||
|
-- Turbine 2 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)
|
||||||
|
if data.turbine1_energy < 0.1 and state == data.lever_on then
|
||||||
|
reactor.activate()
|
||||||
|
end
|
||||||
|
if data.turbine2_energy < 0.1 and state == data.lever_on then
|
||||||
|
reactor.activate()
|
||||||
|
end
|
||||||
|
|
||||||
|
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, 0xff0000)
|
||||||
|
term.setPaletteColor(colors.green, 0x00ff00)
|
||||||
|
term.setPaletteColor(colors.blue, 0x0000ff)
|
||||||
|
|
||||||
|
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, 10)
|
||||||
|
|
||||||
|
parallel.waitForAny(main_loop, function()
|
||||||
|
os.pullEventRaw("terminate")
|
||||||
|
end)
|
||||||
|
|
||||||
|
--os.reboot()
|
||||||
1
emailLua/email.conf
Normal file
1
emailLua/email.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
server_id=15
|
||||||
16
emailLua/emailServ.lua
Normal file
16
emailLua/emailServ.lua
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
local file = fs.open("/disk/email.conf","r")
|
||||||
|
local conf = load("return {"..file.readAll().."}")()
|
||||||
|
local modem = peripheral.wrap("top")
|
||||||
|
modem.open(tonumber(conf.server_id))
|
||||||
|
print("Email server is running...")
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||||
|
if message == "35" then
|
||||||
|
modem.transmit(replyChannel, 15, 135)
|
||||||
|
else
|
||||||
|
-- Here you would handle authentication, e.g. check user:pass
|
||||||
|
print("Received credentials: " .. tostring(message))
|
||||||
|
-- You can add logic to check credentials and respond accordingly
|
||||||
|
end
|
||||||
|
end
|
||||||
16
emailLua/emailclient.lua
Normal file
16
emailLua/emailclient.lua
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
local file = fs.open("/disk/email.conf","r")
|
||||||
|
local conf = load("return {"..file.readAll().."}")()
|
||||||
|
local modem = peripheral.wrap("top")
|
||||||
|
print("What is your username?")
|
||||||
|
local user = io.read()
|
||||||
|
print("Password?")
|
||||||
|
local password = io.read()
|
||||||
|
modem.open(tonumber(conf.server_id))
|
||||||
|
modem.transmit(15, 20, "35")
|
||||||
|
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||||
|
if message ~= 135 then
|
||||||
|
local p = shell.getRunningProgram()
|
||||||
|
shell.run(p)
|
||||||
|
end
|
||||||
|
local userpass = user..":"..pass
|
||||||
|
modem.transmit(15, 20, userpass)
|
||||||
53
git/filePrinter/program.lua
Normal file
53
git/filePrinter/program.lua
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
--local tArgs = { ... }
|
||||||
|
--if #tArgs == 0 then
|
||||||
|
-- local programName = arg[0] or fs.getName(shell.getRunningProgram())
|
||||||
|
-- print("Usage: " .. programName .. " options <path>")
|
||||||
|
-- return
|
||||||
|
--end
|
||||||
|
|
||||||
|
-- Error checking
|
||||||
|
--local sPath = shell.resolve(tArgs[2])
|
||||||
|
--local bReadOnly = fs.isReadOnly(sPath)
|
||||||
|
--if fs.exists(sPath) and fs.isDir(sPath) then
|
||||||
|
-- print("Cannot edit a directory.")
|
||||||
|
-- return
|
||||||
|
--end
|
||||||
|
|
||||||
|
--local lex_context = { line = function() end, report = function() end }
|
||||||
|
|
||||||
|
--local tCompletions
|
||||||
|
--local nCompletion
|
||||||
|
|
||||||
|
--local tCompleteEnv = _ENV
|
||||||
|
--local function complete(sLine)
|
||||||
|
-- if settings.get("edit.autocomplete") then
|
||||||
|
-- local nStartPos = string.find(sLine, "[a-zA-Z0-9_%.:]+$")
|
||||||
|
-- if nStartPos then
|
||||||
|
-- sLine = string.sub(sLine, nStartPos)
|
||||||
|
-- end
|
||||||
|
-- if #sLine > 0 then
|
||||||
|
-- return textutils.complete(sLine, tCompleteEnv)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- return nil
|
||||||
|
--end
|
||||||
|
|
||||||
|
local args = { ... }
|
||||||
|
|
||||||
|
local function printHelp()
|
||||||
|
print("options discription")
|
||||||
|
print("-m program")
|
||||||
|
print("--help or -h help")
|
||||||
|
end
|
||||||
|
|
||||||
|
if args == "--help" or args == "-h" then
|
||||||
|
printHelp()
|
||||||
|
elseif args == "-m" then
|
||||||
|
local fileName = tArgs[2]
|
||||||
|
local file = fs.open(fileName, "r")
|
||||||
|
local data = file.readAll()
|
||||||
|
file.close()
|
||||||
|
print(data.."\n [End Of File]")
|
||||||
|
else
|
||||||
|
printHelp()
|
||||||
|
end
|
||||||
2
git/filePrinter/project.file
Normal file
2
git/filePrinter/project.file
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
url="https://git.astronand.dev/minecartchris/Lua---CC-bs/raw/branch/main/git/filePrinter/"
|
||||||
|
files=["project.file", "program.lua"]
|
||||||
26
git/updater/updater.lua
Normal file
26
git/updater/updater.lua
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
shell.run("ls /git/")
|
||||||
|
print("What project would you like to update?")
|
||||||
|
local projectName = io.read()
|
||||||
|
local URL, projectFile
|
||||||
|
if fs.exists("/git/"..projectName.."/project.file") then
|
||||||
|
local file = fs.open("/git/"..projectName.."/project.file", "r")
|
||||||
|
projectFile = load("return {"..(file.readAll() or "").."}")()
|
||||||
|
file.close()
|
||||||
|
print(textutils.serialise(projectFile))
|
||||||
|
URL = projectFile.url
|
||||||
|
else
|
||||||
|
print("please enter git url or make a project file")
|
||||||
|
URL = io.read()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
fs.delete("/git/"..projectName.."/*")
|
||||||
|
--shell.run("cd /git/"..projectName)
|
||||||
|
local i = 1
|
||||||
|
local list = projectFile.files
|
||||||
|
while i < #list do
|
||||||
|
shell.run("wget "..URL.."/git/ "..projectName.."/"..list[i])
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
--shell.run("wget "..URL.."/git/ "..projectName.."/")
|
||||||
|
shell.run("cd /")
|
||||||
2
git/updater/updaterTest/project.file
Normal file
2
git/updater/updaterTest/project.file
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
url="https://git.astronand.dev/minecartchris/Lua---CC-bs/raw/branch/main/updater/updaterTest",
|
||||||
|
files={"project.file"}
|
||||||
27
reconnectedCC/radon/eventHooks.lua
Normal file
27
reconnectedCC/radon/eventHooks.lua
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
return {
|
||||||
|
start = nil, -- function(version, config, products, shopState)
|
||||||
|
preProduct = nil, -- function(transaction, transactionCurrency, meta, productAddress, products) returns product, errored, errorMessage
|
||||||
|
-- If product is nil, product will be selected by the shop,
|
||||||
|
-- If product is false, customer will be refunded for no product found.
|
||||||
|
-- If product is false and errored is true, customer will be refunded with error message.
|
||||||
|
preStockCheck = nil, -- function(transaction, productsPurchased, products, amountPurchased) returns continueTransaction, errored, errorMessage, invisible
|
||||||
|
prePurchase = nil, -- function(product, amount, refundAmount, transaction, transactionCurrency) returns continueTransaction, errored, errorMessage, invisible
|
||||||
|
purchase = function(product, amount, refundAmount, transaction, transactionCurrency)
|
||||||
|
local DiscordHook = require("DiscordHook")
|
||||||
|
local success, hook = DiscordHook.createWebhook("webhook here")
|
||||||
|
if not success then
|
||||||
|
error("connection failed")
|
||||||
|
end
|
||||||
|
--local product, amount = radon.purchase()
|
||||||
|
|
||||||
|
hook.sendEmbed("your userID here", "Shop", "you shop sold "..amount.." of "..product.name.." using "..transactionCurrency.id)
|
||||||
|
end,
|
||||||
|
failedPurchase = nil, -- function(transaction, transactionCurrency, product, errorMessage)
|
||||||
|
programError = nil, -- function(err)
|
||||||
|
blink = nil, -- function(blinkState) called every 3 seconds while shop is running
|
||||||
|
configSaved = nil, -- function(config) called when config is edited (replaced)
|
||||||
|
productsSaved = nil, -- function(products) called when products object is edited (replaced)
|
||||||
|
onInventoryRefresh = nil, -- function(products, items) called when inventory is refreshed, product quantity can be set through products table
|
||||||
|
onProductSelected = nil, -- function(product, currency) called when product is clicked on the shop screen
|
||||||
|
parallel = nil, -- function() called in parallel constantly. Allowed to be blocking for usage in creating parallel apps.
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user