View difference between Paste ID: sU6mGBxX and zWju7H0z
SHOW: | | - or go back to the newest paste.
1
--[[
2
This program lets you monitor and actively control a Big Reactors reactor and turbines with an OpenComputers computer.
3
4
This program was tested on and designed to work with the mod versions and configurations installed on Flawedspirit's Mental Instability Pack, though as the pack uses default settings for both Big Reactors and OpenComputers, there should be no issues using a different modpack, or even a modpack that makes changes to how BR works.
5
6
- http://technicpack.net/modpack/mi-reloaded.604813
7
- https://flawedspirit.com/minecraft/#pack
8
9
Computer Design
10
------------------------
11
Please note that to keep the code (relatively) simple, the program makes a few assumptions; those being:
12
13
- A Tier 3 Computer
14
- A Tier 2 or better Graphics Card
15
- An Internet Card
16-
- One Tier 2 screen OR one Tier 3 screen (for best results)
16+
- One Tier 2 monitor of dimensions 5 wide by 3 tall
17
- One reactor
18-
- Any number of (or zero) turbines
18+
- Any number of (or none at all) turbines
19
20
Notes
21
------------------------
22
- Only one reactor has been tested with this program (additional reactors added AT OWN RISK)
23-
- Data for only 6 turbines will display onscreen if using a Tier 2 screen
23+
- Data for only 6 turbines will display onscreen
24-
- Data for up to 28 turbines will display onscreen if using a Tier 3 screen
24+
25
- By default, the program updates once every 2 seconds, though the rate is adjustable
26
27
Features
28
------------------------
29
- Dynamic tracking of reactor information, like temperature, fuel/waste levels, coolant levels*, steam output*, or RF storage*
30
- Dynamic tracking of up to 6 turbines, including speed, steam input, RF generation, and RF storage
31
- In-program control of reactor power and control rod settings
32
- Real-time warning if certain parameters indicate abnormal or non-optimal operation of reactors/turbines
33
34-
- NEW! Turbine auto mode! Set it to either 900 or 1800 RPM by pressing T and the program will toggle your turbines' induction coils or active state to keep it at the right speed**
34+
35
36
Usage
37-
** Note: the author takes no responsibility if you bankrupt your base's energy stores because your turbines are all disengaged. Please use responsibly.
37+
38
- Press the left and right arrow keys to toggle between page 1 (turbine/RF storage information) or 2 (control rod configuration)
39
- Press L or , to lower/raise control rods by 1%
40
- Press ; or . to lower/raise control rods by 5%
41
- Press ' or / to lower/raise control rods by 10%
42
- Press P to toggle reactor power
43
- Press Q to exit the program and return to your computer's terminal prompt
44
45
Resources
46
------------------------
47-
- Press T to toggle 'Auto Mode' on all turbines. This will engage the induction coil when your preferred rotational speed (900 or 1800 RPM) is reached
47+
48
  = http://pastebin.com/zWju7H0z
49
- Official OpenComputers Site: http://ocdoc.cil.li/
50
- Official Big Reactors Site: http://www.big-reactors.com/#/
51
- Big Reactors API: http://wiki.technicpack.net/Reactor_Computer_Port
52
53
Changelog
54
------------------------
55
- 0.1.4
56
  - First release to Github! :D
57
58
TODO
59-
- 0.1.6
59+
60-
  - Fixed a bug that caused the program to crash when run on a Tier 2 screen
60+
61-
- 0.1.5
61+
62-
  - Addition of turbine auto mode
62+
- Find a way to display information on ALL turbines that isn't confusing or illogical for the user.
63-
  - Changes to make the program take better advantage of larger screen sizes
63+
64-
  - Bug fixes
64+
65
local component = require("component")
66
local event = require("event")
67
local keyboard = require("keyboard")
68
local os = require("os")
69
local term = require("term")
70
71
local pollRate = 2
72
local active = true
73
local currentPage = 1
74
75
-- Static Text Elements
76
local header = "Reactor: "
77
local headerOutput = "Running at %d%% max rated output"
78
local version = "v0.1.4"
79
80-
local pollRate = 2 -- Change to whatever value you'd like; time is in seconds
80+
81
local gpu = component.gpu
82
local reactor = component.br_reactor
83-
local turbineAutoMode = 0 -- This can be changed to 900 or 1800 if you want
83+
84
85
local turbine = {}
86
local i = 1
87
for address, type in component.list("br_turbine") do
88-
local version = "v0.1.6"
88+
89
  i = i + 1
90
end 
91
92
-- Reactor/turbine Data
93
local totalControlRodLevel = 0
94
local turbineMaxSteamIn = 0
95
local controlRods = {}
96
local reactorStatus = {}
97
98
-- Colors Helper
99
local colors = {}
100
colors.white      = 0xFFFFFF
101
colors.orange     = 0xFFA500
102
colors.magenta    = 0xFF00FF
103
colors.lightblue  = 0x00AEEF
104
colors.yellow     = 0xFFFF00
105
colors.lime       = 0x00FF00
106
colors.pink       = 0xFFC0CB
107
colors.gray       = 0x555555
108
colors.grey       = 0x555555
109
colors.silver     = 0xAAAAAA
110
colors.cyan       = 0x00FFFF
111
colors.purple     = 0x800080
112
colors.blue       = 0x0000FF
113
colors.brown      = 0x603913
114
colors.green      = 0x008000
115
colors.red        = 0xFF0000
116
colors.black      = 0x000000
117
118
-- Returns a whole number expressing a percentage
119
-- out of 100 e.g. 90 is 90%
120
function percent(val, max)
121
  return (val / max) * 100
122
end
123
124
function hLine(row)
125
  gpu.fill(1, row, w, 1, "─")
126
end
127
128
function label(x, y, message, color, ...)
129
  local color = color or gpu.getForeground()
130
  local oldColor = gpu.getForeground()
131
  
132
  gpu.setForeground(color)
133
  term.setCursor(x, y)
134
  print(string.format(message, ...))
135
  gpu.setForeground(oldColor)
136
end
137
138
function box(row, message, color)
139
  --gpu.fill(1, row, w, row + 3, " ")
140
  local color = color or gpu.getForeground()
141
  local oldColor = gpu.getForeground()
142
143
  term.setCursor(1, row)
144
  gpu.setForeground(color)
145
146
  -- Corners
147
  gpu.set(1, row, "╒")
148
  gpu.set(w, row, "╕")
149
  gpu.set(1, row + 2, "└")
150
  gpu.set(w, row + 2, "┘")
151
152
  -- Left and right
153
  gpu.set(1, row + 1, "│")
154
  gpu.set(w, row + 1, "│")
155
156
  -- Top and bottom
157
  gpu.fill(2, row, w - 2, 1, "═")
158
  gpu.fill(2, row + 2, w - 2, 1, "─")  
159
160
  gpu.set(3, row + 1, message)
161
  gpu.setForeground(oldColor)
162
end
163
164
-- Displayed if a reactor cannot be found at all
165
-- and this program is rendered useless
166
function printNoSignal()
167
  icon = "[ ! ] "
168
  message = "No Signal"
169
170
  gpu.setBackground(colors.black)
171
  gpu.fill(1, 1, w, h, " ")
172
173
  gpu.setForeground(colors.red)
174
  gpu.set(w / 2 - (string.len(icon) + string.len(message)) / 2 + 1, (h / 2) + 1, "[ ! ]")
175
176
  gpu.setForeground(colors.white)
177
  gpu.set((w / 2) - 1, (h / 2) + 1, message)
178
end
179
180
-- Event handler for when a key is pressed
181
function onKeyDown(key)
182
  local event, address, _, key, _ = event.pull()
183
  if key == keyboard.keys.right then
184
    currentPage = 2
185
    gpu.fill(1, 1, w, h, " ")
186
  elseif key == keyboard.keys.left then
187
    currentPage = 1
188
    gpu.fill(1, 1, w, h, " ")
189
  elseif key == keyboard.keys.l then
190-
function printControlHelp()
190+
191-
  hLine(h - 5)
191+
192-
  label(1, h - 4, "%s", nil, "l / ,")
192+
193-
  label(16, h - 4, "%s", nil, "; / .")
193+
194-
  label(32, h - 4, "%s", nil, "' / /")
194+
195-
  label(48, h - 4, "%s", nil, "p")
195+
196-
  label(64, h - 4, "%s", nil, "q")
196+
197
  elseif key == keyboard.keys.apostrophe then
198-
  label(1, h - 3, "%s", colors.gray, "Rods +1/-1")
198+
199-
  label(16, h - 3, "%s", colors.gray, "Rods +5/-5")
199+
200-
  label(32, h - 3, "%s", colors.gray, "Rods +10/-10")
200+
201-
  label(48, h - 3, "%s", colors.gray, "Reactor Power")
201+
202-
  label(64, h - 3, "%s", colors.gray, "Quit")
202+
203
  elseif key == keyboard.keys.q then
204-
  if w > 80 then
204+
205-
    label(80, h - 4, "%s", nil, "t")
205+
206-
    label(80, h - 3, "%s", colors.gray, "Turbine Auto Mode")
206+
207
208
-- Listen for "key_down" event to control program flow
209-
function toggleAutoMode()
209+
210-
  if turbineAutoMode == 0 then
210+
211-
    turbineAutoMode = 900
211+
212-
  elseif turbineAutoMode == 900 then
212+
213-
    turbineAutoMode = 1800
213+
214-
  elseif turbineAutoMode == 1800 then
214+
215-
    turbineAutoMode = 0
215+
216
217-
    turbineAutoMode = 0
217+
218
    for i = 1, reactor.getNumberOfControlRods() - 1 do
219
      controlRods[i] = reactor.getControlRodLevel(i)
220
    end
221
222
    -- Iterate through and take the sum of each control rod level
223
    -- Average it to get total control rod level
224
    totalControlRodLevel = 0
225
    for i = 1, #controlRods do
226
      totalControlRodLevel = totalControlRodLevel + controlRods[i]
227
    end
228
    totalControlRodLevel = totalControlRodLevel / #controlRods
229
230
    -- Update reactor data
231
    reactorStatus.temperature      = {"Temp", reactor.getCasingTemperature()}
232
    reactorStatus.fuel             = {"Fuel", reactor.getFuelAmount()}
233
    reactorStatus.waste            = {"Waste", reactor.getWasteAmount()}
234
    reactorStatus.fuelMax          = {"Max Fuel", reactor.getFuelAmountMax()}
235
    reactorStatus.burnRate         = {"Burn Rate", reactor.getFuelConsumedLastTick()}
236
    reactorStatus.reactivity       = {"Reactivity", reactor.getFuelReactivity()}
237
    reactorStatus.coolant          = {"Coolant", reactor.getCoolantAmount()}
238
    reactorStatus.coolantMax       = {"Max Coolant", reactor.getCoolantAmountMax()}
239
    reactorStatus.steam            = {"Steam Out", reactor.getHotFluidProducedLastTick()}
240
    reactorStatus.steamMax         = {"Max Steam", reactor.getHotFluidAmountMax()}
241
    reactorStatus.storedRF         = {"Stored Power", reactor.getEnergyStored()}
242
243
    label(1, 4, "%s: %.3f mB/t (%s: %d%%)", nil, reactorStatus.burnRate[1], reactorStatus.burnRate[2], reactorStatus.reactivity[1], reactorStatus.reactivity[2])
244
245
    -- REACTOR TABLE
246-
  elseif key == keyboard.keys.t then
246+
247-
    toggleAutoMode()
247+
248
    label(16, 6, "%s", nil, reactorStatus.fuel[1])
249
    label(32, 6, "%s", nil, reactorStatus.waste[1])
250
    label(48, 6, "%s", nil, reactorStatus.coolant[1])
251
    label(64, 6, "%s", nil, reactorStatus.steam[1])
252
    hLine(7)
253
254
    -- Table body
255
    label(1, 8, "%d °C", colors.red, reactorStatus.temperature[2])
256
257
    if percent(reactorStatus.fuel[2], reactorStatus.fuelMax[2]) > 10 then
258
      label(16, 8, "%d mB", nil, reactorStatus.fuel[2])
259
    else
260
      label(16, 8, "%d mB [!]", colors.red, reactorStatus.fuel[2])
261
    end
262
263
    if percent(reactorStatus.waste[2], reactorStatus.fuelMax[2]) < 90 then
264
      label(32, 8, "%d mB", nil, reactorStatus.waste[2])
265
    else
266
      label(32, 8, "%d mB [!]", colors.red, reactorStatus.waste[2])
267
    end
268
269
    if percent(reactorStatus.coolant[2], reactorStatus.coolantMax[2]) > 10 then
270
      label(48, 8, "%d mB", nil, reactorStatus.fuel[2])
271
    else
272
      label(48, 8, "%d mB [!]", colors.red, reactorStatus.coolant[2])
273
    end
274
    
275
    if reactorStatus.steam[2] >= turbineMaxSteamIn then
276
      label(64, 8, "%d mB/t", nil, reactorStatus.steam[2])
277
    else
278
      label(64, 8, "%d mB/t [!]", colors.red, reactorStatus.steam[2])
279
    end
280
281
    -- Percentages
282
    label(16, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.fuel[2], reactorStatus.fuelMax[2]))
283
    label(32, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.waste[2], reactorStatus.fuelMax[2]))
284
    label(48, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.coolant[2], reactorStatus.coolantMax[2]))
285
    label(64, 9, "(%.1f%%)", colors.gray, percent(reactorStatus.steam[2], reactorStatus.steamMax[2]))
286
287
    if reactor.getActive() then
288
      label(string.len(header) + 3, 2, "ON", colors.lime)
289
      label(w - string.len(headerOutput), 2, headerOutput, nil, (100 - totalControlRodLevel))
290
    else
291
      label(string.len(header) + 3, 2, "OFF", colors.red)
292
      label((w + 1) - string.len(headerOutput), 2, headerOutput, nil, 0)
293
    end
294
295
    if currentPage == 1 then
296
      box(h - 2, "Press [→] to go to page 2", nil)
297
298
      if component.isAvailable("br_turbine") then
299
        -- TURBINE TABLE
300
        -- Table header
301
        label(1, 11, "%s", nil, "Turbine #")
302
        label(16, 11, "%s", nil, "Speed")
303
        label(32, 11, "%s", nil, "Steam In")
304
        label(48, 11, "%s", nil, "RF Out")
305
        label(64, 11, "%s", nil, "Stored RF")
306
        hLine(12)
307
308
        -- Table body
309
        local turbineTotalSteamIn = 0
310
              turbineMaxSteamIn = 0
311
        local turbineTotalRFOut = 0
312
        local turbineStoredRF = 0
313
314
        -- by default, only 6 turbines will fit on the screen
315
        local maxTurbines = 0
316
        if #turbine > 6 then
317
          maxTurbines = 6
318
          label(1, h - 6, "...", colors.orange)
319
          label(16, h - 6, "%d %s", colors.orange, (#turbine - 6), "turbine(s) not shown.")
320
        else
321
          maxTurbines = #turbine
322
        end
323
324
        for i = 1, maxTurbines do
325
          label(1, 12 + i, "%d", nil, i)
326
          if turbine[i].getRotorSpeed() >= 1780 or turbine[i].getRotorSpeed() <= 1820 then
327
            label(16, 12 + i, "%.1f RPM", colors.lime, turbine[i].getRotorSpeed())
328
          elseif turbine[i].getRotorSpeed() > 1820 then
329
            label(16, 12 + i, "%.1f RPM [!]", colors.red, turbine[i].getRotorSpeed())
330
          else
331
            label(16, 12 + i, "%.1f RPM", colors.orange, turbine[i].getRotorSpeed())
332
          end
333
          label(32, 12 + i, "%d mB/t", nil, turbine[i].getFluidFlowRate())
334
          label(48, 12 + i, "%d RF/t", nil, turbine[i].getEnergyProducedLastTick())
335
          label(64, 12 + i, "%d RF", nil, turbine[i].getEnergyStored())
336
        end
337
338
        for i = 1, #turbine do
339
          turbineTotalSteamIn = turbineTotalSteamIn + turbine[i].getFluidFlowRate()
340
          turbineMaxSteamIn = turbineMaxSteamIn + turbine[i].getFluidFlowRateMax()
341-
      if h > 25 then
341+
342-
        printControlHelp()
342+
343
        end
344
345
        hLine(h - 5)
346
        label(1, h - 4, "%s", nil, "TOTAL")
347
        label(16, h - 4, "%s", nil, "--")
348
        label(32, h - 4, "%d mB/t", nil, turbineTotalSteamIn)
349
        label(48, h - 4, "%d RF/t", nil, turbineTotalRFOut)
350
        label(64, h - 4, "%d RF", nil, turbineStoredRF)
351
      else
352
        label(1, 11, "%s: %d RF", nil, reactorStatus.storedRF[1], reactorStatus.storedRF[2])
353
        label(1, 13, "%s", nil, "No turbines were detected.")
354-
        if w > 80 then
354+
355-
          label(80, 11, "%s", nil, "Coil State")
355+
356
      os.sleep(pollRate)
357
    elseif currentPage == 2 then
358
      local maxBarLength = (w - 11) - 11
359
360-
        -- Update turbine status
360+
361
      label(1, 11, "%s", nil, "Control Rods")
362
      hLine(12)
363
364
      gpu.fill(11, 13, math.ceil(maxBarLength * (totalControlRodLevel / 100) + 0.5), 1, "=")
365
      label(1, 13, "%s", nil, "ALL RODS [")
366
      label(w - 10, 13, "%s %d%%", nil, "]", totalControlRodLevel)
367
368
      hLine(h - 7)
369-
        if h > 25 then
369+
      label(1, h - 6, "%s", nil, "l / ,")
370-
          maxTurbines = math.min(#turbine, 28)
370+
      label(16, h - 6, "%s", nil, "; / .")
371-
          hOffset = 6
371+
      label(32, h - 6, "%s", nil, "' / /")
372
      label(48, h - 6, "%s", nil, "p")
373-
          maxTurbines = math.min(#turbine, 6)
373+
374-
          hOffset = 4
374+
      label(1, h - 5, "%s", colors.gray, "Rods +1/-1")
375
      label(16, h - 5, "%s", colors.gray, "Rods +5/-5")
376
      label(32, h - 5, "%s", colors.gray, "Rods +10/-10")
377-
        if #turbine > maxTurbines then
377+
      label(48, h - 5, "%s", colors.gray, "Reactor Power")
378-
          label(1, h - (hOffset + 2), "...", colors.orange)
378+
379-
          label(16, h - (hOffset + 2), "%d %s", colors.orange, (#turbine - 6), "turbine(s) not shown. Totals shown for all turbines.")
379+
380
    end
381
  else
382
    printNoSignal()
383
  end
384
end
385
386
-- Unregister key_down event on program exit or things get... serious...
387
event.ignore("key_down", onKeyDown)
388-
          -- Auto Mode (TM but not really) fun
388+