Advertisement
Xemrox

Draconic Evolution Reactor Controller

Sep 20th, 2016
2,263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.61 KB | None | 0 0
  1. print("reactor control")
  2.  
  3. local gates = {
  4.     ['drain'] = "flux_gate_5",
  5.     ['charge'] = "flux_gate_6",
  6.     ['shield'] = "flux_gate_7"
  7. }
  8.  
  9. local modem = "right"
  10. local reactor = "top"
  11. local fuel = {
  12.     type = 'block',
  13.     amt = 8
  14. }
  15.  
  16. local coEff = 18
  17. local shieldSafety = {
  18.     stopping = 0.98,
  19.     online = 0.5 --lower this margin to get more energy should be safe
  20. }
  21.  
  22.  
  23. ---DEFUALTS END
  24. local reactorData = {}
  25. local reactorShadow = {
  26.     __index = function(t, k) return reactorShadow[k](t) end,
  27.     canStart = function(self)
  28.         return
  29.         self.temperature >= 2000 and
  30.         self.fieldStrength >= floor(self.maxFieldStrength / 2) and
  31.         self.energySaturation >= floor(self.maxEnergySaturation / 2)
  32.         --self.convertedFuel + this.reactorFuel + self.conversionUnit >= 144
  33.     end,
  34.     canCharge = function(self)
  35.         return self.status ~= "online"
  36.     end,
  37.     canStop = function(self)
  38.         return self.status ~= "offline"
  39.     end
  40. }
  41.  
  42. for k,v in pairs(gates) do
  43.     gates[k] = peripheral.wrap(v)
  44.     gates[k].setOverrideEnabled(true)
  45.     gates[k].setFlowOverride(0)
  46.     gates[k].set = gates[k].setFlowOverride
  47.     gates[k].get = gates[k].getFlow
  48.     gates[k].name = v
  49. end
  50.  
  51. modem = peripheral.wrap(modem)
  52. modem.open(0)
  53.  
  54. reactor = peripheral.wrap(reactor)
  55. local run = true
  56. local floor = math.floor
  57. local commands = {
  58.     exit = function()
  59.         run = false
  60.         return true
  61.     end,
  62.     fetch = function()
  63.         local data = reactorData
  64.         data.gates = {}
  65.         for k,v in pairs(gates) do
  66.             data.gates[k] = v.get()
  67.         end
  68.         return data
  69.     end,
  70.     start = function()
  71.         local result = reactor.activateReactor()
  72.         --print("STARTING", result)
  73.         return result
  74.     end,
  75.     stop = function()
  76.         local result = reactor.stopReactor()
  77.         --print("STOPPING", result)
  78.         return result
  79.     end,
  80.     charge = function()
  81.         local result = reactor.chargeReactor()
  82.         --print("CHARGING")
  83.         return result
  84.     end
  85. }
  86.  
  87. local function convertFuel(fuel)
  88.     if fuel.type == 'nugget' then return fuel.amt * 16 end
  89.     if fuel.type == 'ingot' then return fuel.amt * 144 end
  90.     if fuel.type == 'block' then return fuel.amt * 1296 end
  91.     return 0
  92. end
  93.  
  94. fuel = convertFuel(fuel)
  95. fuel = fuel - convertFuel({type = 'nugget', amt = 1})
  96.  
  97. local function tick(amt)
  98.     if amt ~= nil then
  99.         os.sleep(amt/20)
  100.     else
  101.         os.sleep(1/20)
  102.     end
  103. end
  104.  
  105. local function ShieldRF(reactorData)
  106.     local saturation = (reactorData.energySaturation / reactorData.maxEnergySaturation)
  107.     local baseMaxRFt = floor((reactorData.maxEnergySaturation / 1000.0) * 1.5)
  108.  
  109.     local tempDrainFactor = 0
  110.     if reactorData.temperature > 8000 then
  111.         tempDrainFactor = 1 + ((reactorData.temperature - 8000) * (reactorData.temperature - 8000) * 0.0000025)
  112.     elseif reactorData.temperature > 2000 then
  113.         tempDrainFactor = 1
  114.      elseif reactorData.temperature > 1000 then
  115.         tempDrainFactor = (reactorData.temperature - 1000) / 1000
  116.     else
  117.         tempDrainFactor = 0
  118.     end
  119.  
  120.     --Field Drain Calculation
  121.     local fieldDrain = floor(math.min(tempDrainFactor * (1.0 - saturation) * (baseMaxRFt / 10.923556), math.pow(2,127)))
  122.     local fieldNegPercent = 1.0 - (reactorData.fieldStrength / reactorData.maxFieldStrength)
  123.     local fieldInputRate = fieldDrain / fieldNegPercent
  124.  
  125.     local shieldMod = reactorData.fieldStrength / reactorData.maxFieldStrength * 100;
  126.     if shieldMod < 50 then --we're ~1 tick behind so idle around 50% charge
  127.         fieldInputRate = fieldInputRate * 1.001
  128.     else
  129.         fieldInputRate = fieldInputRate * 0.995
  130.     end
  131.  
  132.     return fieldInputRate
  133. end
  134.  
  135. local function DrainRF(reactorData)
  136.     return math.min(reactorData.energySaturation, reactorData.maxEnergySaturation / 100) / coEff
  137. end
  138.  
  139. local function ChargeRF(reactorData)
  140.     if reactorData.fieldStrength < floor(reactorData.maxFieldStrength / 2) then
  141.         return floor(reactorData.maxFieldStrength / 2)+1;
  142.     elseif reactorData.energySaturation < floor(reactorData.maxEnergySaturation / 2) then
  143.         return floor(reactorData.maxEnergySaturation / 2)+1;
  144.     elseif reactorData.temperature-1 < 2000 then
  145.         return 10 * (2000 - reactorData.temperature+1) * (fuel + 100) * 20;
  146.     end
  147.     return 0
  148. end
  149.  
  150. local function fetchStatus(target)
  151.     local data = reactor.getReactorInfo()
  152.     if type(data) ~= "table" then
  153.         data = {
  154.             fuelConversaionRate = 0,
  155.             temperature = 0,
  156.             fieldStrength = 0,
  157.             fieldDrainRate = 0,
  158.             generationRate = 0,
  159.             status = "invalid",
  160.             energySaturation = 0,
  161.             maxFuelConversion = 0,
  162.             fuelConversion = 0,
  163.             maxFieldStrength = 0,
  164.             maxEnergySaturation = 0,
  165.             shieldRF = 0,
  166.             drainRF = 0,
  167.             chargeRF = 0
  168.         }
  169.     end
  170.     setmetatable(data, reactorShadow)
  171.     data.lastUpdate = os.clock()
  172.     data.shieldRF = ShieldRF(data)
  173.     data.drainRF = DrainRF(data)
  174.     data.chargeRF = ChargeRF(data)
  175.     return data
  176. end
  177.  
  178. reactorData = fetchStatus()
  179.  
  180. local states = {}
  181.  
  182. local function handleOffline()
  183.     --do nothing
  184. end
  185. states.offline = handleOffline
  186.  
  187. local function handleCharge()
  188.     gates.charge.set(reactorData.chargeRF)
  189.     gates.shield.set(0)
  190.     gates.drain.set(0)
  191. end
  192. states.charging = handleCharge
  193.  
  194. local function handleCharged()
  195.     gates.charge.set(0)
  196.     gates.shield.set(0)
  197.     gates.drain.set(0)
  198. end
  199. states.charged = handleCharged
  200.  
  201. local function handleOnline()
  202.     local gen = reactorData.generationRate
  203.     gen = gen - reactorData.shieldRF
  204.     if gen > 0 then
  205.         gates.charge.set(0)
  206.         gates.shield.set(reactorData.shieldRF)
  207.         --local r = math.ceil
  208.         local trueDrain = reactorData.drainRF - (reactorData.shieldRF) -- drainRF - (reactorData.generationRate - shieldRF)
  209.         --print("gR ", r(reactorData.generationRate), " tD ", r(trueDrain), " sRF " , r(shieldRF), " dR " , r(drainRF))
  210.         if trueDrain > 0 then
  211.             gates.drain.set(trueDrain)
  212.         else
  213.             --should not happen...
  214.             --print("trueDrain ", trueDrain, " generationRate ", reactorData.generationRate, " shieldRF " , shieldRF, " t+s ", trueDrain+shieldRF)
  215.             gates.drain.set(gen)
  216.         end
  217.     else
  218.         gates.shield.set(reactorData.shieldRF * shieldSafety.online) --10% safety
  219.         gates.drain.set(0)
  220.         gates.charge.set(gen * -1.1)
  221.     end
  222. end
  223. states.online = handleOnline
  224.  
  225. local function handleStopping()
  226.     local gen = reactorData.generationRate;
  227.     gen = gen - reactorData.shieldRF
  228.     if gen > 0 then
  229.         gates.drain.set(gen * shieldSafety.stopping) --safety margin
  230.         gates.shield.set(reactorData.shieldRF)
  231.         gates.charge.set(0)
  232.     else
  233.         --redirect full energy to shield
  234.         gates.drain.set(0)
  235.         gates.shield.set(reactorData.generationRate)
  236.         --use remaining energy from buffer
  237.         gates.charge.set(-gen)
  238.     end
  239. end
  240. states.stopping = handleStopping
  241.  
  242. states.invalid = function()
  243.     --print("SOMETHING WENT WRONG")
  244.     error("SOMETHING WENT WRONG")
  245. end
  246.  
  247. function control()
  248.     print("control up")
  249.     while run do
  250.         local tmpReactorData = fetchStatus()
  251.         if tmpReactorData.status ~= reactorData.status then
  252.             print(reactorData.status, "->", tmpReactorData.status)
  253.         end
  254.         reactorData = tmpReactorData
  255.         local state = states[reactorData.status]
  256.         if state ~= nil then
  257.             local ok, error = pcall(state)
  258.             if not ok then
  259.                 print(error)
  260.             end
  261.         end
  262.         tick()
  263.     end
  264. end
  265.  
  266. function input()
  267.     print("input up")
  268.     while run do
  269.         local msg = read()
  270.         local cmd = string.lower(msg)
  271.         if commands[cmd] ~= nil then
  272.             print("->", msg)
  273.             local result = commands[cmd]()
  274.             print("<-", result)
  275.             if type(result) == 'table' then
  276.                 for i,v in pairs(result) do
  277.                     print(i, " ", v)
  278.                 end
  279.             end
  280.         else
  281.             print("unkown command ", msg)
  282.         end
  283.     end
  284. end
  285.  
  286. function server()
  287.     print("server up")
  288.     while run do
  289.         local event = {os.pullEvent("modem_message")}
  290.         local cmd = string.lower(event[5])
  291.         if commands[cmd] ~= nil then
  292.             modem.transmit(0,0, textutils.serialize(commands[cmd]()))
  293.         else
  294.             modem.transmit(0,0, "error")
  295.         end
  296.         --print(textutils.serialize(event))
  297.     end
  298. end
  299. parallel.waitForAny(control, input, server)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement