├── examples ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg └── 5.jpg ├── .gitignore ├── install.lua ├── lib └── f.lua ├── README.md └── drmon.lua /examples/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidjazz/drmon/HEAD/examples/1.jpg -------------------------------------------------------------------------------- /examples/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidjazz/drmon/HEAD/examples/2.jpg -------------------------------------------------------------------------------- /examples/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidjazz/drmon/HEAD/examples/3.jpg -------------------------------------------------------------------------------- /examples/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidjazz/drmon/HEAD/examples/4.jpg -------------------------------------------------------------------------------- /examples/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acidjazz/drmon/HEAD/examples/5.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # general 3 | .DS_Store 4 | 5 | # structure 6 | *.swp 7 | *.*~ 8 | 9 | -------------------------------------------------------------------------------- /install.lua: -------------------------------------------------------------------------------- 1 | -- drmon installation script 2 | -- 3 | -- 4 | 5 | local libURL = "https://raw.githubusercontent.com/acidjazz/drmon/master/lib/f.lua" 6 | local startupURL = "https://raw.githubusercontent.com/acidjazz/drmon/master/drmon.lua" 7 | local lib, startup 8 | local libFile, startupFile 9 | 10 | fs.makeDir("lib") 11 | 12 | lib = http.get(libURL) 13 | libFile = lib.readAll() 14 | 15 | local file1 = fs.open("lib/f", "w") 16 | file1.write(libFile) 17 | file1.close() 18 | 19 | startup = http.get(startupURL) 20 | startupFile = startup.readAll() 21 | 22 | 23 | local file2 = fs.open("startup", "w") 24 | file2.write(startupFile) 25 | file2.close() 26 | 27 | -------------------------------------------------------------------------------- /lib/f.lua: -------------------------------------------------------------------------------- 1 | 2 | -- peripheral identification 3 | -- 4 | function periphSearch(type) 5 | local names = peripheral.getNames() 6 | local i, name 7 | for i, name in pairs(names) do 8 | if peripheral.getType(name) == type then 9 | return peripheral.wrap(name) 10 | end 11 | end 12 | return null 13 | end 14 | 15 | -- formatting 16 | 17 | function format_int(number) 18 | 19 | if number == nil then number = 0 end 20 | 21 | local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)') 22 | -- reverse the int-string and append a comma to all blocks of 3 digits 23 | int = int:reverse():gsub("(%d%d%d)", "%1,") 24 | 25 | -- reverse the int-string back remove an optional comma and put the 26 | -- optional minus and fractional part back 27 | return minus .. int:reverse():gsub("^,", "") .. fraction 28 | end 29 | 30 | -- monitor related 31 | 32 | --display text text on monitor, "mon" peripheral 33 | function draw_text(mon, x, y, text, text_color, bg_color) 34 | mon.monitor.setBackgroundColor(bg_color) 35 | mon.monitor.setTextColor(text_color) 36 | mon.monitor.setCursorPos(x,y) 37 | mon.monitor.write(text) 38 | end 39 | 40 | function draw_text_right(mon, offset, y, text, text_color, bg_color) 41 | mon.monitor.setBackgroundColor(bg_color) 42 | mon.monitor.setTextColor(text_color) 43 | mon.monitor.setCursorPos(mon.X-string.len(tostring(text))-offset,y) 44 | mon.monitor.write(text) 45 | end 46 | 47 | function draw_text_lr(mon, x, y, offset, text1, text2, text1_color, text2_color, bg_color) 48 | draw_text(mon, x, y, text1, text1_color, bg_color) 49 | draw_text_right(mon, offset, y, text2, text2_color, bg_color) 50 | end 51 | 52 | --draw line on computer terminal 53 | function draw_line(mon, x, y, length, color) 54 | if length < 0 then 55 | length = 0 56 | end 57 | mon.monitor.setBackgroundColor(color) 58 | mon.monitor.setCursorPos(x,y) 59 | mon.monitor.write(string.rep(" ", length)) 60 | end 61 | 62 | --create progress bar 63 | --draws two overlapping lines 64 | --background line of bg_color 65 | --main line of bar_color as a percentage of minVal/maxVal 66 | function progress_bar(mon, x, y, length, minVal, maxVal, bar_color, bg_color) 67 | draw_line(mon, x, y, length, bg_color) --backgoround bar 68 | local barSize = math.floor((minVal/maxVal) * length) 69 | draw_line(mon, x, y, barSize, bar_color) --progress so far 70 | end 71 | 72 | 73 | function clear(mon) 74 | term.clear() 75 | term.setCursorPos(1,1) 76 | mon.monitor.setBackgroundColor(colors.black) 77 | mon.monitor.clear() 78 | mon.monitor.setCursorPos(1,1) 79 | end 80 | 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![](examples/2.jpg) 3 | > *status*: currently stable, writing documentation 4 | 5 | 6 | # drmon 7 | monitor and failsafe automation for your draconic reactor 8 | 9 | ### what is this 10 | this is a computercraft LUA script that monitors everything about a draconic reactor, with a couple features to help keep it from exploding 11 | NB: This is for Minecraft 1.7.10. You will need to edit references within the code for any version higher to reflect any changes made to Draconic Evolution past its 1.7.10 release. 12 | 13 | 14 | ### tutorial 15 | you can find a very well made youtube tutorial on how to set this up [here](https://www.youtube.com/watch?v=8rBhQP1xqEU) , thank you [The MindCrafters](https://www.youtube.com/channel/UCf2wEy4_BbYpAQcgvN26OaQ) 16 | 17 | ### features 18 | * uses a 3x3 advanced computer touchscreen monitor to interact with your reactor 19 | * automated regulation of the input gate for the targeted field strength of 50% 20 | * adjustable 21 | * immediate shutdown and charge upon your field strength going below 20% 22 | * adjustable 23 | * reactor will activate upon a successful charge 24 | * immediate shutdown when your temperature goes above 8000C 25 | * adjustable 26 | * reactor will activate upon temperature cooling down to 3000C 27 | * adjustable 28 | 29 | * easily tweak your output flux gate via touchscreen buttons 30 | * +/-100k, 10k, and 1k increments 31 | 32 | ### requirements 33 | * one fully setup draconic reactor with fuel 34 | * 1 advanced computer 35 | * 9 advanced monitors 36 | * 3 wired modems, wireless will not work 37 | * a bunch of network cable 38 | 39 | ### installation 40 | * your reactor output flux gate must be setup so that one side of it and one of your stabilizers touches a side of the advanced computer 41 | * by default, flux gate should touch the right side, stabilizer should touch the back of the computer 42 | * if you want to use different sides you need to modify `startup` after you have installed this and specify the sides 43 | * connect a modem to your input flux gate (the one connected to your reactor energy injector) 44 | * connect a modem to your advanced computer 45 | * setup yoru monitors to be a 3x3 and connect a modem to anywhere but the front 46 | * run network cable to all 3 modems 47 | * install this code via running the install script using these commands : 48 | 49 | ``` 50 | > pastebin get Ls1Wg3QQ install 51 | > install 52 | ``` 53 | * modify `startup` if you wish to configure/alter any variables mentioned in the feature list, you'll find them at the top of the file 54 | ``` 55 | > startup 56 | ``` 57 | * you should see stats in your term, and on your monitor 58 | 59 | ### upgrading to the latest version 60 | * right click your computer 61 | * hold ctrl+t until you get a `>` 62 | 63 | ``` 64 | > install 65 | > startup 66 | ``` 67 | 68 | ### known issues 69 | * there is a problem with **skyfactory 2.5** and **pastebin**, see workarounds [here](https://github.com/acidjazz/drmon/issues/9#issuecomment-277910288) 70 | -------------------------------------------------------------------------------- /drmon.lua: -------------------------------------------------------------------------------- 1 | -- modifiable variables 2 | local reactorSide = "back" 3 | local fluxgateSide = "right" 4 | 5 | local targetStrength = 50 6 | local maxTemperature = 8000 7 | local safeTemperature = 3000 8 | local lowestFieldPercent = 15 9 | 10 | local activateOnCharged = 1 11 | 12 | -- please leave things untouched from here on 13 | os.loadAPI("lib/f") 14 | 15 | local version = "0.25" 16 | -- toggleable via the monitor, use our algorithm to achieve our target field strength or let the user tweak it 17 | local autoInputGate = 1 18 | local curInputGate = 222000 19 | 20 | -- monitor 21 | local mon, monitor, monX, monY 22 | 23 | -- peripherals 24 | local reactor 25 | local fluxgate 26 | local inputfluxgate 27 | 28 | -- reactor information 29 | local ri 30 | 31 | -- last performed action 32 | local action = "None since reboot" 33 | local emergencyCharge = false 34 | local emergencyTemp = false 35 | 36 | monitor = f.periphSearch("monitor") 37 | inputfluxgate = f.periphSearch("flux_gate") 38 | fluxgate = peripheral.wrap(fluxgateSide) 39 | reactor = peripheral.wrap(reactorSide) 40 | 41 | if monitor == null then 42 | error("No valid monitor was found") 43 | end 44 | 45 | if fluxgate == null then 46 | error("No valid fluxgate was found") 47 | end 48 | 49 | if reactor == null then 50 | error("No valid reactor was found") 51 | end 52 | 53 | if inputfluxgate == null then 54 | error("No valid flux gate was found") 55 | end 56 | 57 | monX, monY = monitor.getSize() 58 | mon = {} 59 | mon.monitor,mon.X, mon.Y = monitor, monX, monY 60 | 61 | --write settings to config file 62 | function save_config() 63 | sw = fs.open("config.txt", "w") 64 | sw.writeLine(version) 65 | sw.writeLine(autoInputGate) 66 | sw.writeLine(curInputGate) 67 | sw.close() 68 | end 69 | 70 | --read settings from file 71 | function load_config() 72 | sr = fs.open("config.txt", "r") 73 | version = sr.readLine() 74 | autoInputGate = tonumber(sr.readLine()) 75 | curInputGate = tonumber(sr.readLine()) 76 | sr.close() 77 | end 78 | 79 | 80 | -- 1st time? save our settings, if not, load our settings 81 | if fs.exists("config.txt") == false then 82 | save_config() 83 | else 84 | load_config() 85 | end 86 | 87 | function buttons() 88 | 89 | while true do 90 | -- button handler 91 | event, side, xPos, yPos = os.pullEvent("monitor_touch") 92 | 93 | -- output gate controls 94 | -- 2-4 = -1000, 6-9 = -10000, 10-12,8 = -100000 95 | -- 17-19 = +1000, 21-23 = +10000, 25-27 = +100000 96 | if yPos == 8 then 97 | local cFlow = fluxgate.getSignalLowFlow() 98 | if xPos >= 2 and xPos <= 4 then 99 | cFlow = cFlow-1000 100 | elseif xPos >= 6 and xPos <= 9 then 101 | cFlow = cFlow-10000 102 | elseif xPos >= 10 and xPos <= 12 then 103 | cFlow = cFlow-100000 104 | elseif xPos >= 17 and xPos <= 19 then 105 | cFlow = cFlow+100000 106 | elseif xPos >= 21 and xPos <= 23 then 107 | cFlow = cFlow+10000 108 | elseif xPos >= 25 and xPos <= 27 then 109 | cFlow = cFlow+1000 110 | end 111 | fluxgate.setSignalLowFlow(cFlow) 112 | end 113 | 114 | -- input gate controls 115 | -- 2-4 = -1000, 6-9 = -10000, 10-12,8 = -100000 116 | -- 17-19 = +1000, 21-23 = +10000, 25-27 = +100000 117 | if yPos == 10 and autoInputGate == 0 and xPos ~= 14 and xPos ~= 15 then 118 | if xPos >= 2 and xPos <= 4 then 119 | curInputGate = curInputGate-1000 120 | elseif xPos >= 6 and xPos <= 9 then 121 | curInputGate = curInputGate-10000 122 | elseif xPos >= 10 and xPos <= 12 then 123 | curInputGate = curInputGate-100000 124 | elseif xPos >= 17 and xPos <= 19 then 125 | curInputGate = curInputGate+100000 126 | elseif xPos >= 21 and xPos <= 23 then 127 | curInputGate = curInputGate+10000 128 | elseif xPos >= 25 and xPos <= 27 then 129 | curInputGate = curInputGate+1000 130 | end 131 | inputfluxgate.setSignalLowFlow(curInputGate) 132 | save_config() 133 | end 134 | 135 | -- input gate toggle 136 | if yPos == 10 and ( xPos == 14 or xPos == 15) then 137 | if autoInputGate == 1 then 138 | autoInputGate = 0 139 | else 140 | autoInputGate = 1 141 | end 142 | save_config() 143 | end 144 | 145 | end 146 | end 147 | 148 | function drawButtons(y) 149 | 150 | -- 2-4 = -1000, 6-9 = -10000, 10-12,8 = -100000 151 | -- 17-19 = +1000, 21-23 = +10000, 25-27 = +100000 152 | 153 | f.draw_text(mon, 2, y, " < ", colors.white, colors.gray) 154 | f.draw_text(mon, 6, y, " <<", colors.white, colors.gray) 155 | f.draw_text(mon, 10, y, "<<<", colors.white, colors.gray) 156 | 157 | f.draw_text(mon, 17, y, ">>>", colors.white, colors.gray) 158 | f.draw_text(mon, 21, y, ">> ", colors.white, colors.gray) 159 | f.draw_text(mon, 25, y, " > ", colors.white, colors.gray) 160 | end 161 | 162 | 163 | 164 | function update() 165 | while true do 166 | 167 | f.clear(mon) 168 | 169 | ri = reactor.getReactorInfo() 170 | 171 | -- print out all the infos from .getReactorInfo() to term 172 | 173 | if ri == nil then 174 | error("reactor has an invalid setup") 175 | end 176 | 177 | for k, v in pairs (ri) do 178 | print(k.. ": ".. v) 179 | end 180 | print("Output Gate: ", fluxgate.getSignalLowFlow()) 181 | print("Input Gate: ", inputfluxgate.getSignalLowFlow()) 182 | 183 | -- monitor output 184 | 185 | local statusColor 186 | statusColor = colors.red 187 | 188 | if ri.status == "online" or ri.status == "charged" then 189 | statusColor = colors.green 190 | elseif ri.status == "offline" then 191 | statusColor = colors.gray 192 | elseif ri.status == "charging" then 193 | statusColor = colors.orange 194 | end 195 | 196 | f.draw_text_lr(mon, 2, 2, 1, "Reactor Status", string.upper(ri.status), colors.white, statusColor, colors.black) 197 | 198 | f.draw_text_lr(mon, 2, 4, 1, "Generation", f.format_int(ri.generationRate) .. " rf/t", colors.white, colors.lime, colors.black) 199 | 200 | local tempColor = colors.red 201 | if ri.temperature <= 5000 then tempColor = colors.green end 202 | if ri.temperature >= 5000 and ri.temperature <= 6500 then tempColor = colors.orange end 203 | f.draw_text_lr(mon, 2, 6, 1, "Temperature", f.format_int(ri.temperature) .. "C", colors.white, tempColor, colors.black) 204 | 205 | f.draw_text_lr(mon, 2, 7, 1, "Output Gate", f.format_int(fluxgate.getSignalLowFlow()) .. " rf/t", colors.white, colors.blue, colors.black) 206 | 207 | -- buttons 208 | drawButtons(8) 209 | 210 | f.draw_text_lr(mon, 2, 9, 1, "Input Gate", f.format_int(inputfluxgate.getSignalLowFlow()) .. " rf/t", colors.white, colors.blue, colors.black) 211 | 212 | if autoInputGate == 1 then 213 | f.draw_text(mon, 14, 10, "AU", colors.white, colors.gray) 214 | else 215 | f.draw_text(mon, 14, 10, "MA", colors.white, colors.gray) 216 | drawButtons(10) 217 | end 218 | 219 | local satPercent 220 | satPercent = math.ceil(ri.energySaturation / ri.maxEnergySaturation * 10000)*.01 221 | 222 | f.draw_text_lr(mon, 2, 11, 1, "Energy Saturation", satPercent .. "%", colors.white, colors.white, colors.black) 223 | f.progress_bar(mon, 2, 12, mon.X-2, satPercent, 100, colors.blue, colors.gray) 224 | 225 | local fieldPercent, fieldColor 226 | fieldPercent = math.ceil(ri.fieldStrength / ri.maxFieldStrength * 10000)*.01 227 | 228 | fieldColor = colors.red 229 | if fieldPercent >= 50 then fieldColor = colors.green end 230 | if fieldPercent < 50 and fieldPercent > 30 then fieldColor = colors.orange end 231 | 232 | if autoInputGate == 1 then 233 | f.draw_text_lr(mon, 2, 14, 1, "Field Strength T:" .. targetStrength, fieldPercent .. "%", colors.white, fieldColor, colors.black) 234 | else 235 | f.draw_text_lr(mon, 2, 14, 1, "Field Strength", fieldPercent .. "%", colors.white, fieldColor, colors.black) 236 | end 237 | f.progress_bar(mon, 2, 15, mon.X-2, fieldPercent, 100, fieldColor, colors.gray) 238 | 239 | local fuelPercent, fuelColor 240 | 241 | fuelPercent = 100 - math.ceil(ri.fuelConversion / ri.maxFuelConversion * 10000)*.01 242 | 243 | fuelColor = colors.red 244 | 245 | if fuelPercent >= 70 then fuelColor = colors.green end 246 | if fuelPercent < 70 and fuelPercent > 30 then fuelColor = colors.orange end 247 | 248 | f.draw_text_lr(mon, 2, 17, 1, "Fuel ", fuelPercent .. "%", colors.white, fuelColor, colors.black) 249 | f.progress_bar(mon, 2, 18, mon.X-2, fuelPercent, 100, fuelColor, colors.gray) 250 | 251 | f.draw_text_lr(mon, 2, 19, 1, "Action ", action, colors.gray, colors.gray, colors.black) 252 | 253 | -- actual reactor interaction 254 | -- 255 | if emergencyCharge == true then 256 | reactor.chargeReactor() 257 | end 258 | 259 | -- are we charging? open the floodgates 260 | if ri.status == "charging" then 261 | inputfluxgate.setSignalLowFlow(900000) 262 | emergencyCharge = false 263 | end 264 | 265 | -- are we stopping from a shutdown and our temp is better? activate 266 | if emergencyTemp == true and ri.status == "stopping" and ri.temperature < safeTemperature then 267 | reactor.activateReactor() 268 | emergencyTemp = false 269 | end 270 | 271 | -- are we charged? lets activate 272 | if ri.status == "charged" and activateOnCharged == 1 then 273 | reactor.activateReactor() 274 | end 275 | 276 | -- are we on? regulate the input fludgate to our target field strength 277 | -- or set it to our saved setting since we are on manual 278 | if ri.status == "online" then 279 | if autoInputGate == 1 then 280 | fluxval = ri.fieldDrainRate / (1 - (targetStrength/100) ) 281 | print("Target Gate: ".. fluxval) 282 | inputfluxgate.setSignalLowFlow(fluxval) 283 | else 284 | inputfluxgate.setSignalLowFlow(curInputGate) 285 | end 286 | end 287 | 288 | -- safeguards 289 | -- 290 | 291 | -- out of fuel, kill it 292 | if fuelPercent <= 10 then 293 | reactor.stopReactor() 294 | action = "Fuel below 10%, refuel" 295 | end 296 | 297 | -- field strength is too dangerous, kill and it try and charge it before it blows 298 | if fieldPercent <= lowestFieldPercent and ri.status == "online" then 299 | action = "Field Str < " ..lowestFieldPercent.."%" 300 | reactor.stopReactor() 301 | reactor.chargeReactor() 302 | emergencyCharge = true 303 | end 304 | 305 | -- temperature too high, kill it and activate it when its cool 306 | if ri.temperature > maxTemperature then 307 | reactor.stopReactor() 308 | action = "Temp > " .. maxTemperature 309 | emergencyTemp = true 310 | end 311 | 312 | sleep(0.1) 313 | end 314 | end 315 | 316 | parallel.waitForAny(buttons, update) 317 | 318 | --------------------------------------------------------------------------------