This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
dragonlord's profile picture

Redstone Flux Control Center (RFCC) - EU fork now available!

Started by dragonlord, 15 May 2014 - 04:45 AM
dragonlord #1
Posted 15 May 2014 - 06:45 AM
This started as a frustration with EnderIO's Power Monitor, and the need for a more robust power management system.

Do you have an RF-based power grid that you want to know the status at a glance?

Do you want to consolidate all your RF-based storage devices and make them work as one?

Do you need to have your Big Reactor come online when your magmatic dynamos can't handle the load?

Look no further.

Presenting the Redstone Flux Control Center (RFCC) v0.3!

RFCC is the latest in Redstone Flux Technology. With the help of ComputerCraft and OpenPeripherals, we can now build complex, heterogenous, RF-based power grids with minimal fuss.

Do you have Resonant Energy Cells and Ultimate Energy Cubes from Mekanism? Do you want to see how much power is flowing thru your energy conduits? RFCC will recognize them just fine.

RFCC was built with expansion in mind. With the hotplug subsystem, you can add and remove devices from the grid, without having to touch the config or restarting RFCC.

Constrained by 6 block sides? Conect all your storage devices and monitors via wired modems.

Need to turn on your reactor when your grid is low on power? RFCC emits a redstone signal when it reaches the low power threshold, and will turn off when it reaches normal levels.


Features:
  1. Dashboard - shows the summary of your power grid. You can check the details of each capacitor on the grid simply by clicking (on the native console) or right clicking on an external monitor.
  2. Hotplug subsystem - Allows adding and removal of peripherals from your network, on the fly! No need to mess around with the configuration. No need to restart the program. If RFCC detects a valid RF device, it'll add it to the grid immediately.
  3. Multi-monitor support - do you want to have a dashboard in your power plant, and in your house? No problem. Just hook up an advanced monitor to your grid, and turn them on via the Monitor Selection screen.

Minimum requirements:

Computercraft 1.6
OpenPeripherals
Thermal Expansion 3


Installation:

Please note: RFCC only works with Advanced Computers and Advanced Monitors. Advanced Turtles may work, but not tested (and the UI may not look as good).

Just run this command in your advanced computer to install RFCC as a startup program:

pastebin get TfeHE7Wy startup

Future versions of RFCC will use the same pastebin.

On first startup, RFCC will generate its default configuration file, and ask you to inspect it first before running. Once you're happy with the settings, just run RFCC again.

When a new version of RFCC is released, updating is easy. Just run

startup update

And it will download the update from the same pastebin. Useful if you have a lot of sub-grids.



Notes about the Hotplug Subsystem:

While I've done my best to ensure that the hotplug subsystem is sane for use, it's not perfect. When removing a storage device or monitor, you must turn off the connected modem first. If you don't, this will result in "ghost" devices: the computer still sees the device as connected, even though it's not. And in this scenario, you will have to restart the computer.

If you need to be able to add and remove storage devices on the fly, consider using a Peripheral Proxy.


Tutorial:

Spoiler[media]http://www.youtube.com/watch?v=_8XWQJ1atbw[/media]


IC2 (EU) Support:

SpoilerWhile I don't support IC2, Hansbald made a fork of RFCC for those who want to monitor their MFSU's.

You can get his fork by running the following:


pastebin get jRVSBmSE eucc


Enjoy!
Edited on 24 May 2014 - 03:30 AM
VerTiGo_Etrex #2
Posted 17 May 2014 - 10:30 PM
Awesome! This is exactly what I needed for my Big Reactor system :)/>
Goo #3
Posted 19 May 2014 - 02:09 PM
This is amazing, i've watched your video 3 times:) unfortunately, i've run into a problem… For some reason, it wont start the program, it only says: startup:183: attept to call table …. Aaand im a starter at CC, ive never made a program, and im so lost:( what am i doing wrong? Ive copied everything you did, step by step on your video… Thanks in advance for helping me:)
awsmazinggenius #4
Posted 19 May 2014 - 04:00 PM
Read your error. You are attempting to call a table. Look at the code. He probably made a typo.
Goo #5
Posted 19 May 2014 - 04:11 PM
It says startup:183: attempt to call table. Nothing else:( and as i said, i dont really know much about programming… I look at it and i cant really say anything :P/>
Hansbald #6
Posted 19 May 2014 - 04:55 PM
Hey,
Can you modify/tell me how to modify it so it displays EU from MFSU's? That would be really awesome :P/> I use this on my server :)/>
dragonlord #7
Posted 20 May 2014 - 04:15 AM
It says startup:183: attempt to call table. Nothing else:( and as i said, i dont really know much about programming… I look at it and i cant really say anything :P/>/>

What version of CC are you using? It should be the latest. That line of code is only available to CC 1.6 and later.
dragonlord #8
Posted 20 May 2014 - 04:23 AM
Hey,
Can you modify/tell me how to modify it so it displays EU from MFSU's? That would be really awesome :P/>/> I use this on my server :)/>/>

From my understanding of openperipherals, the method name should be the same, regardless if it's an MFSU or an RF-based device. In other words, you can use this directly. You'll probably just have to find and replace all "RF" to "EU" for the labels.

If that's not the case, you will need to check what are the methods exposed via the peripheral API to get the current reading and max storage. Then look for the constants section, and edit the method names.
Hansbald #9
Posted 20 May 2014 - 03:27 PM
Hey,
Can you modify/tell me how to modify it so it displays EU from MFSU's? That would be really awesome :P/>/> I use this on my server :)/>/>

From my understanding of openperipherals, the method name should be the same, regardless if it's an MFSU or an RF-based device. In other words, you can use this directly. You'll probably just have to find and replace all "RF" to "EU" for the labels.

If that's not the case, you will need to check what are the methods exposed via the peripheral API to get the current reading and max storage. Then look for the constants section, and edit the method names.

I just tried that, nope not the same methods, I changed the constants to the MFSU ones, but I get all kinds of errors I can't seem to fix…

One of them is too many arguments on the addCapacitor thingy
dragonlord #10
Posted 21 May 2014 - 01:36 AM
Hey,
Can you modify/tell me how to modify it so it displays EU from MFSU's? That would be really awesome :P/>/> I use this on my server :)/>/>

From my understanding of openperipherals, the method name should be the same, regardless if it's an MFSU or an RF-based device. In other words, you can use this directly. You'll probably just have to find and replace all "RF" to "EU" for the labels.

If that's not the case, you will need to check what are the methods exposed via the peripheral API to get the current reading and max storage. Then look for the constants section, and edit the method names.

I just tried that, nope not the same methods, I changed the constants to the MFSU ones, but I get all kinds of errors I can't seem to fix…

One of them is too many arguments on the addCapacitor thingy

If that's the case, then that means you have no choice but to modify the addCapacitors() and getReading() methods. Those two methods assume that the methods to be called on the peripherals require one parameter (Forge direction).
Hansbald #11
Posted 21 May 2014 - 05:05 PM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked
apemanzilla #12
Posted 21 May 2014 - 08:28 PM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked
There's multiple versions of cclite available for 1.6, including:
My fork
Gamax's fork
The original by Sorroko

Additionally, Mimic is available for 1.5 in a slightly buggy form, and if you can get your hands on a copy of the old CCEmu there's that for 1.5 (and it probably is the best one with the least bugs, too)

If you need 1.6, I'd recommend my version of cclite for ease of use as it has a menu option to open the data folder, or if either works then CCEmu would be better.
Edited on 21 May 2014 - 06:29 PM
dragonlord #13
Posted 21 May 2014 - 11:47 PM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked

What's wrong with editing your program directly via your favorite editor? No need to copy/paste. Just save and run.
Hansbald #14
Posted 22 May 2014 - 04:03 PM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked

What's wrong with editing your program directly via your favorite editor? No need to copy/paste. Just save and run.

I'm stupid :P/> Thanks for reminding me you can edit outside of minecraft ._.


Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked
There's multiple versions of cclite available for 1.6, including:
My fork
Gamax's fork
The original by Sorroko

Additionally, Mimic is available for 1.5 in a slightly buggy form, and if you can get your hands on a copy of the old CCEmu there's that for 1.5 (and it probably is the best one with the least bugs, too)

If you need 1.6, I'd recommend my version of cclite for ease of use as it has a menu option to open the data folder, or if either works then CCEmu would be better.

Thank you so much :)/>

I nearly finished it just have one problem:

this:
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]
returns a function and not a value?!
Am I missing something?

(GET_ENERY_STORED_FUNCTION_MFSU is getEUStored)

if I just do getEUStored in another programm it works fine
Edited on 22 May 2014 - 03:51 PM
NassiC #15
Posted 22 May 2014 - 04:28 PM
Hi
Cool program, it looks like just the thing i need. But im a fool with all this programing stuff, never learned it at all… When i start the program, i follow your steps to the letter, i get this error: startup:183: attept to call table

I saw there was another dude who got the same error, but non of that helped me out. I am useing version 1.63 of cc, so that shouldnt be the problem and i have no clue how i can look at or fix the code my self. So i hope you can help me get it working… :)/>

/NassiC
apemanzilla #16
Posted 22 May 2014 - 05:00 PM
Thank you so much :)/>

I just built my version of CCLite, so you can just use one of those downloads if you don't want the extra setup. (here)
Hansbald #17
Posted 22 May 2014 - 06:06 PM
Thank you so much :)/>

I just built my version of CCLite, so you can just use one of those downloads if you don't want the extra setup. (here)
Thanks already got it :)/>
Just need to find out why it is not returning a function and not a number like it should be…
dragonlord #18
Posted 23 May 2014 - 06:51 AM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked

What's wrong with editing your program directly via your favorite editor? No need to copy/paste. Just save and run.

I'm stupid :P/> Thanks for reminding me you can edit outside of minecraft ._.


Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked
There's multiple versions of cclite available for 1.6, including:
My fork
Gamax's fork
The original by Sorroko

Additionally, Mimic is available for 1.5 in a slightly buggy form, and if you can get your hands on a copy of the old CCEmu there's that for 1.5 (and it probably is the best one with the least bugs, too)

If you need 1.6, I'd recommend my version of cclite for ease of use as it has a menu option to open the data folder, or if either works then CCEmu would be better.

Thank you so much :)/>

I nearly finished it just have one problem:

this:
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]
returns a function and not a value?!
Am I missing something?

(GET_ENERY_STORED_FUNCTION_MFSU is getEUStored)

if I just do getEUStored in another programm it works fine

This code
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]

Should read as
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU](yourParametersHereIfNecessary)

Without the parenthesis, you're just doing a regular table lookup, and not a function call.
dragonlord #19
Posted 23 May 2014 - 06:57 AM
Hi
Cool program, it looks like just the thing i need. But im a fool with all this programing stuff, never learned it at all… When i start the program, i follow your steps to the letter, i get this error: startup:183: attept to call table

I saw there was another dude who got the same error, but non of that helped me out. I am useing version 1.63 of cc, so that shouldnt be the problem and i have no clue how i can look at or fix the code my self. So i hope you can help me get it working… :)/>

/NassiC

Line 183 is this:

local nativeTerm = term.native()

term.native() is a CC 1.6 API. It won't work on lower versions.

Are you using a modpack? Or you made your own? My first suspicion is an API conflict, which might be caused by 2 different CC versions installed in the same modpack.
NassiC #20
Posted 23 May 2014 - 09:04 AM
Hi
Cool program, it looks like just the thing i need. But im a fool with all this programing stuff, never learned it at all… When i start the program, i follow your steps to the letter, i get this error: startup:183: attept to call table

I saw there was another dude who got the same error, but non of that helped me out. I am useing version 1.63 of cc, so that shouldnt be the problem and i have no clue how i can look at or fix the code my self. So i hope you can help me get it working… :)/>

/NassiC

Line 183 is this:

local nativeTerm = term.native()

term.native() is a CC 1.6 API. It won't work on lower versions.

Are you using a modpack? Or you made your own? My first suspicion is an API conflict, which might be caused by 2 different CC versions installed in the same modpack.

Thanks for your answer… :)/>

I am useing the Crackpack modpack from atlauncer. From what i can see, they use cc version 1.63.
How can i check if there is 2 defrent versions installed?
I get the same error in bot a singler player and on my server. If that makes it easyer any defrence… :)/>

/NassiC
Hansbald #21
Posted 23 May 2014 - 12:58 PM
Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked

What's wrong with editing your program directly via your favorite editor? No need to copy/paste. Just save and run.

I'm stupid :P/> Thanks for reminding me you can edit outside of minecraft ._.


Is there a computercraft 1.6 emulator yet? It's really annoying to change a line of code and C&P it into minecraft to see if it worked
There's multiple versions of cclite available for 1.6, including:
My fork
Gamax's fork
The original by Sorroko

Additionally, Mimic is available for 1.5 in a slightly buggy form, and if you can get your hands on a copy of the old CCEmu there's that for 1.5 (and it probably is the best one with the least bugs, too)

If you need 1.6, I'd recommend my version of cclite for ease of use as it has a menu option to open the data folder, or if either works then CCEmu would be better.

Thank you so much :)/>

I nearly finished it just have one problem:

this:
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]
returns a function and not a value?!
Am I missing something?

(GET_ENERY_STORED_FUNCTION_MFSU is getEUStored)

if I just do getEUStored in another programm it works fine

This code
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]

Should read as
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU](yourParametersHereIfNecessary)

Without the parenthesis, you're just doing a regular table lookup, and not a function call.

Oh wow I'm so stupid sometimes *facepalm*
Just need to fix this graphical error :/


It shouldn't draw the UI twice lol
(Only one MFSU is connected)

Just fixed this error by resetting the monitor

Incase anyone needs smth like this:
pastebin get jRVSBmSE eucc
Edited on 23 May 2014 - 04:42 PM
dragonlord #22
Posted 23 May 2014 - 04:37 PM
Hi
Cool program, it looks like just the thing i need. But im a fool with all this programing stuff, never learned it at all… When i start the program, i follow your steps to the letter, i get this error: startup:183: attept to call table

I saw there was another dude who got the same error, but non of that helped me out. I am useing version 1.63 of cc, so that shouldnt be the problem and i have no clue how i can look at or fix the code my self. So i hope you can help me get it working… :)/>

/NassiC

Line 183 is this:

local nativeTerm = term.native()

term.native() is a CC 1.6 API. It won't work on lower versions.

Are you using a modpack? Or you made your own? My first suspicion is an API conflict, which might be caused by 2 different CC versions installed in the same modpack.

Thanks for your answer… :)/>

I am useing the Crackpack modpack from atlauncer. From what i can see, they use cc version 1.63.
How can i check if there is 2 defrent versions installed?
I get the same error in bot a singler player and on my server. If that makes it easyer any defrence… :)/>

/NassiC

That is very weird.

I just installed Crack Pack 1.5.0.0-TCP, and it works as expected.

I also checked the contents of the mods folder, and everything seems good.

Now I'm wondering what your setup looks like. Below's a screenshot of mine.

Spoiler
dragonlord #23
Posted 23 May 2014 - 05:01 PM
Ok, I just checked the older version of Crack Pack (1.1.1.0-TCP), and it uses ComputerCraft 1.58, which I can't (and will not) support.

Please upgrade to the latest version of Crack Pack.

For those running other modpacks, to know your version of CC, just reboot any computer or turtle. It should show the OS type (CraftOS or TurtleOS), with the CC version number. It has to be at least 1.6.
Edited on 23 May 2014 - 04:45 PM
dragonlord #24
Posted 24 May 2014 - 05:26 AM
pastebin get jRVSBmSE eucc

I edited the original post. :D/>
Hansbald #25
Posted 24 May 2014 - 05:56 PM
pastebin get jRVSBmSE eucc

I edited the original post. :D/>
Thanks! :)/>
madsamjp #26
Posted 25 July 2014 - 03:36 PM
Hi there, just started using your program an I find it fantastic! However I have one question, is there a way to display just a total energy percentage for all power peripherals connected? I have 48 energy cubes connected to my main power grid, so individual cube information is kind of unnecessary however a total energy percentage would be very useful! Thanks :)/>
hbomb79 #27
Posted 27 July 2014 - 08:41 AM
This looks like a very good program, Doing almost the same as my security suite program that has yet to be released… very well done!
Zenith2012 #28
Posted 16 August 2014 - 08:27 AM
Hi dragonlord,

Firstly, thank you for creating and sharing this script. It is exactly what I was looking for and works perfectly. I've hacked it about a little bit, I've basically created a startup script that ensures the main script is always up to date (re-downloads the script from pastebin on reboot).

But, more importantly I've hacked in some code from here and added in basic support for a single wireless modem so that the power grid computer can turn my BigReactor on/off. Essentially, in your code where you enable/disable the redstone output I put a line that sends a "poweron" or "poweroff" to my reactor computer that then does the work :)/>

I might look to upgrading the script on the reactor itself so that when it is on, it maintains optimum temperature by moving the control rods, but that's something to worry about in the future, as the reactor itself is emergency power only.

I was wondering, if you had any plans to add in support for wireless monitors (if that's possible)?

Thanks,

Zenith
instinx #29
Posted 17 August 2014 - 05:35 PM
@Zenith Any chance of posting your code to enable wireless modem support?
@Dragonlord I just started building this on my server and it is awesome! Many thanks!
xriscarter #30
Posted 21 September 2014 - 06:17 PM
I am using the newest versions of CC and EnderIO but when I go to add a wired modem to the capasitor bank and right click it the modem does not turn on (turn red). Does anyone have any ideas as to why when all my other modems work find?
NullSchritt #31
Posted 29 September 2014 - 08:56 AM
@xriscarter do you have open peripherals installed?
sorcexi #32
Posted 12 February 2015 - 10:15 PM
so ive been messing around with this amazing management system u have but i cant seem to add in Mekanisms energy cubes, your system will detect it as a peripheral but it will not add it to the capacitors list. ive tried to add some code into yours to make it find the capacitor but no avail. posted code below is taken from yours and the EU fork. it works just fine detects it as a peripheral but wont add the Cubes to the capacitor list.

Spoiler

– EU Control Center (EUCC) v0.3


– Main configuration
local tArgs = {…}
local CONFIG_FILE = "power_conf"

local CONFIG_TEMPLATE = [[– adjust these configuration options as necessary.
– delay for checking all capacitors
TICK_DELAY = ${tickDelay}

– threshold in percentages
GREEN_ZONE = ${greenZone}
YELLOW_ZONE = ${yellowZone}

NORMAL_POWER_THRESHOLD = ${nomalPowerThreshold}
LOW_POWER_THRESHOLD = ${lowPowerThreshold}

– configures what side to emit when low power
– a valid side is required.
SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = "${sideForRedstone}"

– Active monitors on startup
MONITORS_ACTIVE = ${monitorsActive}
]]

local MONITORS_ACTIVE = {}

do
if #tArgs > 0 and tArgs[1] == "update" then
print("This fork doesnt support update yet :(/>")
end
end

local function interpolate(s, params)
return s:gsub('($%b{})', function(w) return params[w:sub(3, -2)] or w end)
end

local function saveSettings()
local h = fs.open("/"..CONFIG_FILE, "w")

local settings = {
tickDelay = TICK_DELAY or 100,
greenZone = GREEN_ZONE or 70,
yellowZone = YELLOW_ZONE or 30,
nomalPowerThreshold = NORMAL_POWER_THRESHOLD or 90,
lowPowerThreshold = LOW_POWER_THRESHOLD or 10,
sideForRedstone = SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER or "bottom",
monitorsActive = textutils.serialize(MONITORS_ACTIVE)
}

h.write(interpolate(CONFIG_TEMPLATE, settings))
h.close()
end


if fs.exists(CONFIG_FILE) == false then
print("Isgards Control Center")
print("I can't find my configuration file.")
print("Generating one for you.")

saveSettings()

print("")
print("Configuration file is located at /"..CONFIG_FILE)
print("You may edit this file to change my default settings.")
print("Once satisfied, run me again.")
return
else
os.unloadAPI(CONFIG_FILE)

if os.loadAPI("/"..CONFIG_FILE) == false then
error("Could not load the config file!")
end

CONFIG = nil
for k, v in pairs(_G) do
if k == CONFIG_FILE then
CONFIG = v
break
end
end

if CONFIG == nil then
print("I could not find the necessary config.")
print("You probably screwed something up.")
error()
end
end

term.setCursorPos(1, 1)
term.clear()
print("Starting EU Control Center…")
sleep(2)















– Constants
local GET_ENERGY_STORED_FUNCTION="getEnergyStored"
local GET_MAX_ENERGY_STORED_FUNCTION="getMaxEnergyStored"

local GET_ENERGY_STORED_FUNCTION_MFSU="getEUStored"
local GET_MAX_ENERGY_STORED_FUNCTION_MFSU="getEUCapacity"

local GET_ENERGY_STORED_FUNCTION_CUBE="getEnergyStored"
local GET_MAX_ENERGY_STORED_FUNCTION_CUBE="getMaxEnergyStored"

local TICK_DELAY = CONFIG.TICK_DELAY
local PAUSE_TIME_IN_SECONDS = TICK_DELAY / 20

– threshold in percentages
local GREEN_ZONE = CONFIG.GREEN_ZONE
local YELLOW_ZONE = CONFIG.YELLOW_ZONE

local NORMAL_POWER_THRESHOLD = CONFIG.NORMAL_POWER_THRESHOLD
local LOW_POWER_THRESHOLD = CONFIG.LOW_POWER_THRESHOLD

– configures what side to emit when low power
local SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = CONFIG.SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER

MONITORS_ACTIVE = CONFIG.MONITORS_ACTIVE

– state variables
local clickableLines = {}
local clickableOutputMonitors = {}
local monitors = {}
local capacitors = {}
local dashboardButtons = {}
local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0

– Capacitor basic functions
do
capacitors.add = function(params)
table.insert(capacitors, params)
end

capacitors.get = function(name)
for i, v in ipairs(capacitors) do
if name == v.name then
return v
end
end

return nil
end

capacitors.remove = function(name)
local found = nil
for i, v in ipairs(capacitors) do
if name == v.name then
found = i
break
end
end

if found then
table.remove(capacitors, found)
end
end

capacitors.clear = function()
for i, v in ipairs(capacitors) do
capacitors = nil
end
end
end


– Special Windows
local nativeDisplayTabs = {}
local nativeMonitorTabWindow
local consoleWindow
local monitorSelectionWindow

do
local nativeTerm = term.native()
local width, height = term.getSize()
local x, y = 1, 2
local newWidth, newHeight = width, height - 1

nativeTerm.setCursorPos(x, y)

nativeMonitorTabWindow = window.create(nativeTerm, 1, 1, width, 1, false)

consoleWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
consoleWindow.active = true

monitorSelectionWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
monitorSelectionWindow.active = true
end

– TODO: break up this humongous script into smaller chunks that can be loaded
– via os.loadAPI().


– basic functions
local function tableSize(targetTable)
local i = 0
for k, v in pairs(targetTable) do
i = i + 1
end

return i
end

local function padRight(text, width, padCharacter)
if width == nil then
width = term.getSize()
end

padCount = width - string.len(text)

if padCharacter == nil then
padCharacter = " "
end

if padCount > 0 then
return text..string.rep(padCharacter, padCount)
else
return text
end
end

local function padLeft(text, width, padCharacter)
if width == nil then
width = term.getSize()
end

padCount = width - string.len(text)

if padCharacter == nil then
padCharacter = " "
end

if padCount > 0 then
return string.rep(padCharacter, padCount)..text
else
return text
end
end

local function printZoneText(percent, callback)
if percent >= GREEN_ZONE then
term.setTextColor(colors.green)
elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
term.setTextColor(colors.yellow)
else
term.setTextColor(colors.red)
end

callback()

term.setTextColor(colors.white)
end

local function resetRedstoneState()
for k,v in pairs(rs.getSides()) do
rs.setOutput(v, false)
end
end
– basic functions


– line drawing API
local function drawVerticalLine(targetWindow, x, y, height)
targetWindow.setCursorPos(x, y)

targetWindow.setBackgroundColor(colors.blue)
for i = 1, height do
targetWindow.write(" ")
targetWindow.setCursorPos(x, i)
end
targetWindow.setBackgroundColor(colors.black)
end

local function drawHorizontalLine(targetWindow, x, y, width)
targetWindow.setCursorPos(x, y)
targetWindow.setBackgroundColor(colors.blue)
targetWindow.write(string.rep(" ", width))
targetWindow.setBackgroundColor(colors.black)
end
– line drawing API


– window management
local console = {
log = function(message)
local currentTerm = term.current()
term.redirect(consoleWindow)

print(message)

term.redirect(currentTerm)
end
}

local function showWindows(…)
for i, v in ipairs(arg) do
if v.active == true then
v.setVisible(true)
else
v.setVisible(false)
end
end
end

local function hideWindows(…)
for i, v in ipairs(arg) do
v.setVisible(false)
end
end

local function getCursorPositionRelativeToParent(currentWindow)
– determine offset of current window from parent
local x, y = currentWindow.getPosition()
local xOffset, yOffset = x - 1, y - 1

local cursorX, cursorY = currentWindow.getCursorPos()
return cursorX + xOffset, cursorY + yOffset
end

local function createInformationWindow(parentWindow)
local width, height = parentWindow.getSize()

local widthOffset = 2
local heightOffset = 2

local windowWidth = width - (widthOffset * 2)
local windowHeight = height - (heightOffset * 2)

local informationWindow = window.create(parentWindow, 1 + widthOffset, 1 + heightOffset, windowWidth, windowHeight, false)
informationWindow.active = false

drawHorizontalLine(informationWindow, 1, 1, windowWidth)
drawHorizontalLine(informationWindow, 1, windowHeight, windowWidth)

drawVerticalLine(informationWindow, 1, 1, windowHeight)
drawVerticalLine(informationWindow, windowWidth, 1, windowHeight)

return informationWindow
end

local function createSummaryWindow(parentWindow, x, y)
local width, height = parentWindow.getSize()

– we make use of the parent window's cursor position to make it more convenient.
local x, y = parentWindow.getCursorPos()
local newHeight = height - (y - 1)

local summaryWindow = window.create(parentWindow, x, y, width, newHeight, false)
summaryWindow.active = false

return summaryWindow
end

local function printToWindow(targetWindow, widthOffset, text)
local x, y = targetWindow.getCursorPos()
local width, height = targetWindow.getSize()
local maxTextSize = width - (widthOffset * 2)

targetWindow.write(text:sub(1, maxTextSize))
targetWindow.setCursorPos(x, y+1)
end

local function createDashboardWindows(parentWindow)
– order is important here!
local summaryWindow = createSummaryWindow(parentWindow)
summaryWindow.active = true
local informationWindow = createInformationWindow(parentWindow)
informationWindow.active = false

local windows = {
[1] = summaryWindow,
[2] = informationWindow,

getSummaryWindow = function()
return summaryWindow
end,

getInformationWindow = function()
return informationWindow
end
}

return windows
end

local function initializeNativeDisplayTabs()
local nativeTerm = term.native()
nativeTerm.setCursorPos(1, 2)

local dashboardWindows = createDashboardWindows(nativeTerm)

table.insert(nativeDisplayTabs, {
tab = {
label = "Dashboard",
event = "dashboard_clicked",
active = true,
startX = 0,
startY = 0
},

windows = dashboardWindows
})
table.insert(nativeDisplayTabs, {
tab = {
label = "Monitors",
event = "monitors_clicked",
startX = 0,
startY = 0
},

windows = { monitorSelectionWindow }
})
table.insert(nativeDisplayTabs, {
tab = {
label = "Console",
event = "console_clicked",
startX = 0,
startY = 0
},

windows = { consoleWindow }
})

nativeDisplayTabs.getSelectedTab = function(x, y)
if x == nil or y == nil then
return nil
end

for i, v in ipairs(nativeDisplayTabs) do
local tab = v.tab
local withinX = x >= tab.startX and x <= tab.endX
local withinY = y >= tab.startY and y <= tab.endY

if withinX and withinY then
return i
end
end

return nil
end

nativeDisplayTabs.setSelectedTab = function(selected)
for i, v in ipairs(nativeDisplayTabs) do
if i == selected then
v.tab.active = true
else
v.tab.active = false
end
end
end

nativeDisplayTabs.getActiveTab = function()
for i, v in ipairs(nativeDisplayTabs) do
if v.tab.active == true then
return i
end
end
end

nativeDisplayTabs.getDashboardWindows = function()
return dashboardWindows
end
end

– window management


–Name check

local function findPeripheral(_type)
for _,name in pairs(peripheral.getNames()) do
if peripheral.getType(name) == _type then
return peripheral.wrap(name)
end
end
end

–TODO

– capacitor management
local function addCapacitors(…)
local peripheralList = arg


if #peripheralList == 0 then
peripheralList = peripheral.getNames()
capacitors.clear()
end

for i, p in ipairs(peripheralList) do
local currentPeripheral = peripheral.wrap(p)


if currentPeripheral[GET_ENERGY_STORED_FUNCTION_MFSU] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU] ~= nil and currentPeripheral[GET_ENERGY_STORED_FUNCTION_CUBE] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION_CUBE] ~= nil and currentPeripheral[GET_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_ENERGY_STORED_FUNCTION]("north") ~= nil then
console.log("Adding new capacitor: "..p)
capacitors.add({
name = p,
peripheral = currentPeripheral,
lastReading = 0,
flowRate = 0,
percent = 0
})
end


end
end

local function removeCapacitors(…)
for i, k in ipairs(arg) do
capacitors.remove(k)
end
end

local function getReading()
local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0

local currentReading = 0
local capacity = 0

for i, v in ipairs(capacitors) do


currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_MFSU]() or 0
capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU]() or 0
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION_CUBE]() or 0
capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_CUBE]() or 0
currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION]("north") or 0
capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north") or 0

–error(currentReading)
if currentReading ~= nil then
v.flowRate = (currentReading - v.lastReading) / TICK_DELAY
v.lastReading = currentReading

if capacity == 0 then
v.percent = 0
else
v.percent = math.floor((currentReading / capacity) * 100)
end

totalEnergyAvailable = totalEnergyAvailable + v.lastReading
totalFlowRate = totalFlowRate + v.flowRate
end

totalCapacity = totalCapacity + capacity
end

local sortByLastReading = function(a, B)/>
return a.percent > b.percent
end

table.sort(capacitors, sortByLastReading)

return totalEnergyAvailable, totalCapacity, totalFlowRate
end

local function emitRedstoneSignalOnLowPower(percent)
if percent < LOW_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == false then
console.log("Low power threshold reached.")
rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, true)
elseif percent >= NORMAL_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == true then
console.log("Back to normal power levels.")
rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, false)
end
end
– capacitor management


– monitor management
local function addMonitors(…)
local monitorList = arg

if #monitorList == 0 then
monitorList = peripheral.getNames()
monitors = {}
end

for i, m in ipairs(monitorList) do
local currentPeripheral = peripheral.wrap(m)

if "monitor" == peripheral.getType(m) and currentPeripheral.isColour() == true then
console.log("Adding new monitor: "..m)
currentPeripheral.setCursorPos(1, 1)
monitors[m] = {
peripheral = currentPeripheral,
windows = createDashboardWindows(currentPeripheral),
active = false
}
end
end
end

local function removeMonitors(…)
local activeMonitorsCount = tableSize(MONITORS_ACTIVE)

for i, k in ipairs(arg) do
monitors[k] = nil
dashboardButtons[k] = nil
MONITORS_ACTIVE[k] = nil
end

if activeMonitorsCount ~= tableSize(MONITORS_ACTIVE) then
saveSettings()
end
end
– monitor management


– hotplug system
local function doWhileMonitorSuspended(callback)
os.queueEvent("pause_monitor")
callback()
os.queueEvent("resume_monitor")
end

local function hotplugPeripherals()
while true do
local event, name = os.pullEvent()
local callback = nil

if event == "peripheral" then
console.log("Detected new peripheral: "..name)

callback = function()
addMonitors(name)
addCapacitors(name)
end
elseif event == "peripheral_detach" then
console.log("Peripheral removed: "..name)

callback = function()
removeMonitors(name)
removeCapacitors(name)
end
elseif event == "monitor_resize" then
console.log("Monitor resized: "..name)

callback = function()
monitors[name].peripheral.setCursorPos(1, 1)
monitors[name].windows = createDashboardWindows(monitors[name].peripheral)
dashboardButtons[name] = nil

if monitors[name].active == true then
showWindows(unpack(monitors[name].windows))
end
end
end

if callback ~= nil then
doWhileMonitorSuspended(callback)
end
end
end
– hotplug system


– information window for the capacitors
local function addClickableLine(monitorName, key, currentY)
clickableLines[monitorName][key] = {
line = currentY
}
end

local function toggleInformationWindow(summaryWindow, informationWindow, capacitorName)
if capacitorName == nil then
summaryWindow.active = true
informationWindow.active = false
else
summaryWindow.active = not summaryWindow.active
informationWindow.active = not informationWindow.active
end

local capacitor = capacitors.get(capacitorName)

if informationWindow.active == true then
widthOffset = 3
heightOffset = 3

informationWindow.setCursorPos(widthOffset, heightOffset)
local width, height = informationWindow.getSize()
local labelWidth = width - (widthOffset * 2)
local capacity = 0
–Capcacity
if(findPeripheral("mfsu")) then
capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_MFSU]()
elseif(findPeripheral("cube")) then
capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION_CUBE]()
else
capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north")
end
–Capacity


printToWindow(informationWindow, widthOffset, "Capacitor name:")
printToWindow(informationWindow, widthOffset, padRight(" "..capacitorName, labelWidth))
printToWindow(informationWindow, widthOffset, "Capacitor type:")
printToWindow(informationWindow, widthOffset, padRight(" "..peripheral.getType(capacitorName), labelWidth))
printToWindow(informationWindow, widthOffset, "Capacity:")
printToWindow(informationWindow, widthOffset, padRight(" "..capacity.." EU", labelWidth))
printToWindow(informationWindow, widthOffset, "Available:")
printToWindow(informationWindow, widthOffset, padRight(" "..capacitor.lastReading.." EU", labelWidth))

local closeLabel = " Click anywhere to close "

local x = math.floor(((width - string.len(closeLabel)) / 2 ) + 0.5)

informationWindow.setCursorPos(x, height-2)

informationWindow.setBackgroundColor(colors.red)
informationWindow.write(closeLabel)
informationWindow.setBackgroundColor(colors.black)
end

showWindows(summaryWindow, informationWindow)
end

local function checkForSelectableLine(monitorName, x, y)
if clickableLines[monitorName] == nil then
return nil
end

for k,v in pairs(clickableLines[monitorName]) do
if y == v.line then
return k
end
end

return nil
end

local function getSelectedDashboardButton(monitorName, x, y)
if x == nil or y == nil then
return nil
end

local v = dashboardButtons[monitorName]

local nextButtonSelected = (x >= v.next.startX and x <= v.next.endX) and (y >= v.next.startY and y <= v.next.endY)
local prevButtonSelected = (x >= v.prev.startX and x <= v.prev.endX) and (y >= v.prev.startY and y <= v.prev.endY)

if nextButtonSelected then
return "next"
elseif prevButtonSelected then
return "prev"
end

return nil
end

– information window for the capacitors


– main display
local function renderPaginationButtons(monitorName, max)
local width, height = term.getSize()
local nextButton = " Next "
local previousButton = " Prev "
local spacer = " "

local dashboardButtonsToRender = previousButton..spacer..nextButton
local buttonOffset = (width - (string.len(dashboardButtonsToRender))) / 2

term.setCursorPos(buttonOffset, height)
local x, y = getCursorPositionRelativeToParent(term.current())

if dashboardButtons[monitorName] == nil then
dashboardButtons[monitorName] = {
prev = {
startX = x,
startY = y,
endX = x,
endY = y
},

next = {
startX = x,
startY = y,
endX = x,
endY = y
},

offset = 1,
max = max
}
end

if dashboardButtons[monitorName].offset == 1 then
dashboardButtons[monitorName].max = max
end

term.setBackgroundColor(colors.red)
term.write(previousButton)
dashboardButtons[monitorName].prev.endX, dashboardButtons[monitorName].prev.endY = getCursorPositionRelativeToParent(term.current())

term.setBackgroundColor(colors.black)
term.write(spacer)

dashboardButtons[monitorName].next.startX, dashboardButtons[monitorName].next.startY = getCursorPositionRelativeToParent(term.current())
term.setBackgroundColor(colors.red)
term.write(nextButton)
dashboardButtons[monitorName].next.endX, dashboardButtons[monitorName].next.endY = getCursorPositionRelativeToParent(term.current())

term.setBackgroundColor(colors.black)
end

local function writeSummary(monitorName, totalEnergyAvailable, totalCapacity, totalFlowRate)
local width, height = term.getSize()
local gridLabel = os.getComputerLabel() or "No name set"
local gridLabelOffset = (width - (string.len(gridLabel))) / 2

term.setCursorPos(gridLabelOffset, 1)
term.write(gridLabel)
term.setCursorPos(1, 3)

print(padRight("Total Capacitors: "..tostring(#capacitors)))
print(padRight("Max Energy Storage: "..totalCapacity.." EU"))

local totalPercentRemaining = math.floor((totalEnergyAvailable / totalCapacity) * 100)
emitRedstoneSignalOnLowPower(totalPercentRemaining)

if totalEnergyAvailable > totalCapacity then
printZoneText(totalPercentRemaining, function() print(padRight("Energy Available: "..totalCapacity.." EU")) end)
else
printZoneText(totalPercentRemaining, function() print(padRight("Energy Available: "..totalEnergyAvailable.." EU")) end)
end


if totalFlowRate < 0 then
term.setTextColor(colors.red)
elseif totalFlowRate > 0 then
term.setTextColor(colors.green)
else
term.setTextColor(colors.white)
end

print(padRight("Flow Rate: "..totalFlowRate.." EU/t"))
term.setTextColor(colors.white)

local currentX, currentY = term.getCursorPos()
term.setCursorPos(1, currentY+1)

clickableLines[monitorName] = {}
local pagination = dashboardButtons[monitorName] or {}
local offset = pagination.offset or 1

local count = 0
for i = offset, #capacitors do
local v = capacitors
local name = string.format(" %03d", i)..": "
local percent = v.percent

printZoneText(percent, function() term.write(name) end)

local labelLength = string.len(name)
local powerBarLength = width - labelLength - 1
local powerBarReading = math.floor((width - labelLength - 1) * (percent/100))

local zoneColor = colors.red
local textColor = colors.white
if percent >= GREEN_ZONE then
zoneColor = colors.green
elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
zoneColor = colors.yellow
textColor = colors.blue
end

local stats = padRight(string.format(" %d", percent).."%, "..v.flowRate.." EU/t", powerBarLength)

term.setTextColor(textColor)
term.setBackgroundColor(zoneColor)
j = 1
for c in stats:gmatch(".") do
if(j>powerBarReading) then
term.setBackgroundColor(colors.black)
end

term.write©

j = j + 1
end
term.setTextColor(colors.white)
term.setBackgroundColor(colors.black)

local currentX, currentY = getCursorPositionRelativeToParent(term.current())
addClickableLine(monitorName, v.name, currentY)

local termX, termY = term.getCursorPos()
term.setCursorPos(1, termY+2)
count = count + 1

if termY > (height - 4) then
max = count
break
end
end

local currentX, currentY = term.getCursorPos()
for k = currentY, height-1 do
term.setCursorPos(1, k)
term.clearLine()
end

renderPaginationButtons(monitorName, count)
end

local function displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, targetMonitor)
local listOfSummaryWindows = {
native = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
}

for k, v in pairs(monitors) do
listOfSummaryWindows[k] = v.windows.getSummaryWindow()
end

for k, v in pairs(listOfSummaryWindows) do
if targetMonitor == nil or (k == targetMonitor) then
local currentTerm = term.current()

term.redirect(v)

writeSummary(k, totalEnergyAvailable, totalCapacity, totalFlowRate)

term.redirect(currentTerm)

if k == targetMonitor then
return
end
end
end
end

local function monitorCapacitors()
totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0

while true do
– show reading
displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate)

– need to call this first to get most current sample
getReading()

local samplingTimer = os.startTimer(PAUSE_TIME_IN_SECONDS)
while true do
local event, p1 = os.pullEvent()
if event == "timer" and p1 == samplingTimer then
totalEnergyAvailable, totalCapacity, totalFlowRate = getReading()
break
elseif event == "pause_monitor" then
os.pullEvent("resume_monitor")
break
end
end
end
end

local function changePages(monitor, x, y, isInformationWindowActive)
local selectedButton = getSelectedDashboardButton(monitor, x, y)
local showSummary = false

if selectedButton == "next" and not isInformationWindowActive then
local newOffset = dashboardButtons[monitor].offset + (dashboardButtons[monitor].max or 0)
if newOffset <= #capacitors then
dashboardButtons[monitor].offset = newOffset

showSummary = true
end
elseif selectedButton == "prev" and not isInformationWindowActive then
local newOffset = dashboardButtons[monitor].offset - (dashboardButtons[monitor].max or 0)
if newOffset > 0 then
dashboardButtons[monitor].offset = newOffset
else
dashboardButtons[monitor].offset = 1
end

showSummary = true
end

if showSummary then
displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, p1)
return true
end

return false
end

local function nativeDashboardHandler()
while true do
local event, x, y = os.pullEvent("dashboard_clicked")
local isInformationWindowActive = nativeDisplayTabs.getDashboardWindows().getInformationWindow().active

if not changePages("native", x, y, isInformationWindowActive) then
local selectedCapacitor = checkForSelectableLine("native", x, y)

local summaryWindow = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
local informationWindow = nativeDisplayTabs.getDashboardWindows().getInformationWindow()

toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
end
end
end

local function monitorDashboardHandler()
while true do
local event, monitor, x, y = os.pullEvent("monitor_touch")

if monitors[monitor].active == true then
local summaryWindow = monitors[monitor].windows.getSummaryWindow()
local informationWindow = monitors[monitor].windows.getInformationWindow()

if not changePages(monitor, x, y, informationWindow.active) then
local selectedCapacitor = checkForSelectableLine(monitor, x, y)
toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
end
end
end
end
– main display


– monitor selection screen (if monitor is attached)
local function addClickableOutputMonitor(k, currentY)
clickableOutputMonitors[k] = {
line = currentY
}
end

local function toggleMonitor(monitorName)
monitors[monitorName].active = not monitors[monitorName].active

if monitors[monitorName].active then
console.log("Enabling "..monitorName)
MONITORS_ACTIVE[monitorName] = true
else
console.log("Disabling "..monitorName)
MONITORS_ACTIVE[monitorName] = nil

hideWindows(unpack(monitors[monitorName].windows))
monitors[monitorName].peripheral.setBackgroundColor(colors.black)
monitors[monitorName].peripheral.clear()
end

saveSettings()
end

local function showMonitorSelection(targetWindow)
local currentTerm = term.current()

term.redirect(targetWindow)
term.setCursorPos(1, 1)
term.clear()

local width, height = term.getSize()

if tableSize(monitors) > 0 then
printToWindow(term, 0, "Select Output Monitor: ")
else
printToWindow(term, 0, "No Monitors found.")
end

printToWindow(term, 0, "")

local currentX, currentY = term.getCursorPos()
term.setCursorPos(currentX + 2, currentY)

clickableOutputMonitors = {}
for k, v in pairs(monitors) do
currentX, currentY = getCursorPositionRelativeToParent(targetWindow)
term.setBackgroundColor(colors.black)

if v.active == true then
term.setBackgroundColor(colors.blue)
showWindows(unpack(v.windows))
end

label = padRight(" "..k, width-4)
printToWindow(term, 0, label)

addClickableOutputMonitor(k, currentY)
end
term.setBackgroundColor(colors.black)

term.redirect(currentTerm)

while true do
local event, x, y = os.pullEvent()

if "monitors_clicked" == event then
for k, v in pairs(clickableOutputMonitors) do
if v.line == y then
toggleMonitor(k)
return
end
end
elseif event == "peripheral" or event == "peripheral_detach" then
coroutine.yield()
return
end
end
end

local function monitorSelection()
for k, v in pairs(MONITORS_ACTIVE) do
if monitors[k] then
monitors[k].active = true
end
end

while true do
showMonitorSelection(monitorSelectionWindow)
end
end

local function nativeDisplay()
while true do
local currentTerm = term.current()

term.redirect(nativeMonitorTabWindow)
nativeMonitorTabWindow.setVisible(true)

term.setCursorPos(1, 1)
term.setBackgroundColor(colors.gray)
term.clearLine()
term.setTextColor(colors.yellow)

for i, v in ipairs(nativeDisplayTabs) do
hideWindows(unpack(v.windows))
end

for i, v in ipairs(nativeDisplayTabs) do
local tab = v.tab
tab.startX, tab.startY = getCursorPositionRelativeToParent(term.current())

if tab.active then
term.setBackgroundColor(colors.black)
showWindows(unpack(v.windows))
else
term.setBackgroundColor(colors.gray)
end

term.write(" "..tab.label.." ")
tab.endX, tab.endY = getCursorPositionRelativeToParent(term.current())
end
term.setTextColor(colors.white)
term.redirect(currentTerm)

while true do
local event, selectedTab = os.pullEvent("selected_tab")

if selectedTab then
nativeDisplayTabs.setSelectedTab(selectedTab)
break
end
end
end
end

local function mouseClickEventMonitor()
while true do
local event, type, x, y = os.pullEvent("mouse_click")
local selectedTab = nativeDisplayTabs.getSelectedTab(x, y)

if selectedTab and nativeDisplayTabs.getDashboardWindows().getInformationWindow().active == false then
os.queueEvent("selected_tab", selectedTab)
elseif selectedTab == nil then
local activeTab = nativeDisplayTabs[nativeDisplayTabs.getActiveTab()]

os.queueEvent(activeTab.tab.event, x, y)
end
end
end

– Initialization
initializeNativeDisplayTabs()
resetRedstoneState()
addCapacitors()
addMonitors()

while true do
parallel.waitForAll(mouseClickEventMonitor, nativeDisplay, monitorSelection, hotplugPeripherals, monitorCapacitors, nativeDashboardHandler, monitorDashboardHandler)
end
dragonlord #33
Posted 20 February 2015 - 03:14 PM
First off, I'd like to thank everyone. I made this program almost a year ago, and it seems that alot are interested in it.

I haven't been playing Minecraft for more than 6 months due to real life responsibilities, so it's been a while since the last time I touched the codebase.

@Zenith2012: Once I get back to playing (very soon), I'll get a chance to check it out. Wireless monitors support is a good idea. Let's see.

@sorcexi you're not the first one to encounter problems with Mekanism. I built this program back when it was still 1.6.4. Mekanism support was dependent on OpenPeripherals. For Minecraft 1.7, It's either a change in the OpenPeripherals API, or a bug in Mekanism. I will take a look as soon as I get my hands on a 1.7 modpack with Mekanism.
falconraptor #34
Posted 20 June 2015 - 05:31 PM
@dragonlord and @sorcexi, I have modified RFCC to have mekanism v8 support in 1.7.10.
I might also look in to the wireless because it sounds like a great idea.
Here is the pastebin code: ZbPQ2FjU
I did change the autoupdate to point to that code as well.
Edited on 20 June 2015 - 04:32 PM
jpoblocki #35
Posted 23 July 2015 - 04:15 AM
I cant seem to get the modems to connect wither and I have the newest of the mods for 1.6.4 with computer craft 1.6 annyone know how to fi the modems not connecting to energy cells?
KingofGamesYami #36
Posted 23 July 2015 - 04:35 AM
@jpoblocki Which mods do you have? If I'm not mistaken, you're missing a version of OpenPeripherals that supports energy cells.
jpoblocki #37
Posted 23 July 2015 - 09:11 PM
@jpoblocki Which mods do you have? If I'm not mistaken, you're missing a version of OpenPeripherals that supports energy cells.

i just have the standard tekkit package. I will checking OpenPeripherals versions tho and report back

ComputerCraft 1.7 newest is 1.7.10 compatible only i have tekkit 1.6.4 thats why its not working i think\
lpenap #38
Posted 28 November 2015 - 01:51 AM
Greetings!,

Hey dlord, I'm currently playing with FTB Infinity 1.7.10 and liked this program very much.

I have updated your original code to include the following features:

* More accurate method for calculating RF/t from capacitors (The error margin was very high and I was getting wrong readings with lots of engines, reactors and capacitors/cells)
* Debug parameter to show additional info on console every time a new capacitor is added.
* Support for EnderIO multiblocks capacitor banks (only need to attach a single block from the entire multiblock) (additional configuration required once the capacitor is attached. Check the instructions in the pastebin link)

For those who want to upgrade, this is the link: http://pastebin.com/2vkaXfBZ

Feel free to merge back with your code.

Installs with:


pastebin get 2vkaXfBZ startup

Includes all the original RFCC features.
Yanniclord #39
Posted 27 January 2016 - 08:30 PM
Can anyone add support for Thermal Expansion Energy Cells? Everytime i try connecting them, i get "powered_tile", but the script crashes at line 489 "first argument needs to be a number or nil".

I found this (http://pastebin.com/cA2TNNdH). That one supports "powered_tile" blocks, but doesnt look far as good as RFCC does, and also RFCC has multi page setup, wich is awesome, but the fact it doesnt support half of the RF generating/storing blocks, is actually sad.
Edited on 27 January 2016 - 07:31 PM
AppleDash48 #40
Posted 08 June 2016 - 04:59 AM
Having some problems here…I've got 71 resonant energy cells and an ender IO capacitor hooked up, and when I try to connect them to the computer and run this program, it outputs:

"startup:489: first argument needs to be a number or nil"

Alas, I am unfortunately not sure exactly what the problem is. (unless the support for this many periphs. isn't supported in computer craft?)
Bomb Bloke #41
Posted 08 June 2016 - 05:20 AM
You might be better off with a different script; the author of this one hasn't logged in for over a year.

At a glance, though, I'd guess it has something to do with the version of OpenPeripheral in use.