Advertisement
FredMSloniker

Reactor.lua

Dec 21st, 2020 (edited)
1,405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local computer = require("computer")
  2. local component = require("component")
  3. local event = require("event")
  4. local term = require("term")
  5.  
  6. -- control just one reactor per computer. Simpler that way.
  7. local reactor
  8. do
  9.     local t = component.list("nc_fission_reactor")
  10.     if not next(t) then -- none!
  11.         print("Error: no reactors found!")
  12.         os.exit()
  13.     end
  14.     if next(t, (next(t))) then -- more than one!
  15.         print("Error: this program can only control one reactor!")
  16.         os.exit()
  17.     end
  18.     reactor = component.nc_fission_reactor
  19. end
  20. local isproblem = function()
  21.     local problem = reactor.getProblem()
  22.     if (problem == "No Problem") and (reactor.getFissionFuelName() == "No Fuel") then problem = "No Fuel" end
  23.     return problem
  24. end
  25. reactor.deactivate() -- just so we know.
  26.  
  27. -- scale a number in the 0 to 1 range to an integer in the 1 to n range in such a way that all integers are equally represented.
  28. local scalenumber = function(x, n)
  29.     return math.floor(math.max(math.min(x * n + 1, n), 1))
  30. end
  31.  
  32. -- stubs for term not being available.
  33. local t = {
  34.     drawdisplay = function(t)
  35.         if isproblem() ~= "No Problem" then computer.beep(440, .1) end
  36.     end,
  37.     err = function(s)
  38.         print(s)
  39.         os.exit()
  40.     end,
  41. }
  42. -- set up display stuff.
  43. if term.isAvailable() then
  44.     local gpu = component.gpu
  45.     local sf, sb = gpu.setForeground, gpu.setBackground
  46.     t.err = function(s)
  47.         sf(0xffffff)
  48.         sb(0x000000)
  49.         term.clear()
  50.         term.write(s, true)
  51.         os.exit()
  52.     end
  53.     sf(0xffffff)
  54.     sb(0x000000)
  55.     term.clear()
  56.     local colorscreen = gpu.getDepth() ~= 1
  57.     local width, height = gpu.maxResolution()
  58.     local aspectratio = 1
  59.     width = math.min(width, height * aspectratio * 2) -- * 2 because of character size
  60.     -- we want the height to be a multiple of 4 plus 3.
  61.     height = math.floor((width / 2 / aspectratio - 3) / 4) * 4 + 3
  62.     -- resize the width accordingly.
  63.     width = math.floor(height * 2 * aspectratio)
  64.     -- and set bar tops and height.
  65.     local barheight = math.floor((height - 3) / 4)
  66.     local bartops = {
  67.         energy = 1,
  68.         heat = 2 + barheight,
  69.         fueltime = 3 + barheight * 2,
  70.         runtime = 4 + barheight * 3
  71.     }
  72.     gpu.setResolution(width, height)
  73.     local sevenths = {
  74.         energy = {0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0xffff00, 0xff8000, 0xff0000},
  75.         heat = {0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0xffff00, 0xff8000, 0xff0000},
  76.         fueltime = {0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00},
  77.         runtime = {0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00}
  78.     }
  79.     if not colorscreen then
  80.         for i = 1, 7 do
  81.             sevenths.energy[i] = 0xffffff
  82.         end
  83.         sevenths.heat, sevenths.fueltime, sevenths.runtime = sevenths.energy, sevenths.energy, sevenths.energy
  84.     end
  85.     -- draw a line of the display.
  86.     local line = function(bartype, x, y, isblack)
  87.         sb(isblack and 0 or sevenths[bartype][scalenumber((x - 1) / (width - 1), 7)])
  88.         gpu.fill(x, bartops[bartype], 1, y, " ")
  89.     end
  90.     -- initialize the display.
  91.     for bartype, wedges in pairs(sevenths) do
  92.         for x = 1, width do
  93.             line(bartype, x, barheight)
  94.         end
  95.     end
  96.    
  97.     local lastreadings = {energy = -1, heat = -1, fueltime = -1, runtime = -1}
  98.     local lastnoproblem = true
  99.     local operatingtrack = {}
  100.     for i = 1, width do table.insert(operatingtrack, false) end
  101.     local tickson = 0
  102.     local currenttick = 0
  103.    
  104.     -- draw the display.
  105.     t.drawdisplay = function(t)
  106.         sf(0xffffff)
  107.         currenttick = (currenttick % width) + 1
  108.         if t.reactoron ~= operatingtrack[currenttick] then
  109.             tickson = tickson + (t.reactoron and 1 or -1)
  110.             operatingtrack[currenttick] = t.reactoron
  111.         end
  112.         t.runtime, t.reactoron = tickson / width, nil
  113.         for bartype, fraction in pairs(t) do
  114.             local reading = scalenumber(fraction, width)
  115.             if lastreadings[bartype] ~= reading then
  116.                 line(bartype, lastreadings[bartype], math.floor(barheight / 2))
  117.                 line(bartype, reading, math.floor(barheight / 2), true)
  118.                 lastreadings[bartype] = reading
  119.             end
  120.         end
  121.         local problem = isproblem()
  122.         local noproblem = (problem == "No Problem")
  123.         if lastnoproblem ~= noproblem then
  124.             problem = string.format("Error: %s!", problem)
  125.             problem = string.format("%s%s", string.rep(" ", math.floor((width - problem:len()) / 2)), problem)         
  126.             sf(0xff0000)
  127.             for _, bartype in pairs({"heat", "fueltime", "runtime"}) do
  128.                 local y = bartops[bartype] - 1
  129.                 gpu.fill(1, y, width - 1, 1, " ")
  130.                 if not noproblem then
  131.                     term.setCursor(1, y)
  132.                     term.write(problem)
  133.                 end
  134.             end
  135.             sf(0x000000)
  136.             lastnoproblem = noproblem
  137.         end
  138.         if not noproblem then computer.beep(440, .1) end
  139.     end
  140. end
  141. local drawdisplay, err = t.drawdisplay, t.err
  142.  
  143. local scrub = function(reason)
  144.     reactor.deactivate()
  145.     err(string.format("%s! Shutting down reactor.", reason))
  146. end
  147.  
  148. local MaxEnergyStoredConstant, MaxHeatLevelConstant = reactor.getMaxEnergyStored(), reactor.getMaxHeatLevel()
  149.  
  150. -- and here we go.
  151. computer.beep(440, .1)
  152. repeat
  153.     local keypress = event.pull(0, "key_down")
  154.     if keypress then scrub("Keypress detected") end
  155.     local status = {
  156.         energy = reactor.getEnergyStored() / MaxEnergyStoredConstant,
  157.         heat = reactor.getHeatLevel() / MaxHeatLevelConstant,
  158.         fueltime = reactor.getFissionFuelTime(),
  159.     }
  160.     if status.fueltime ~= 0 then status.fueltime = 1 - reactor.getCurrentProcessTime() / status.fueltime end -- avoiding divide by zero for no fuel
  161.     status.reactoron = (status.energy <= 0.5) and (status.heat <= 0.5)
  162.     reactor[status.reactoron and "activate" or "deactivate"]()
  163.     drawdisplay(status)
  164. until false
  165.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement