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 | + |