Mod Feedback ChromatiCraft questions and suggestions

JOBGG

New Member
Jul 29, 2019
62
0
0
Hmmm...couldn't you cache the last used path and only recalculate when that path fails or new nodes are added? In order to prevent it from searching the entire structure when no connection can be found, you could so some connected component precalculation and just check whether there are any pylons of said color in the component the consumer is in. Using an algorithm such as A* might still be preferable even if you don't care about the shortest path since shorter paths require less looking up, and given that you're working with an euclidean space, creating an admissible heuristic is pretty straightforward.
 

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
Hmmm...couldn't you cache the last used path and only recalculate when that path fails or new nodes are added? In order to prevent it from searching the entire structure when no connection can be found, you could so some connected component precalculation and just check whether there are any pylons of said color in the component the consumer is in. Using an algorithm such as A* might still be preferable even if you don't care about the shortest path since shorter paths require less looking up, and given that you're working with an euclidean space, creating an admissible heuristic is pretty straightforward.
I do cache successful paths, but that does not help when there is no valid path for a given color.
 

JOBGG

New Member
Jul 29, 2019
62
0
0
That's what I was suggesting connected components for. You have a set for every node and keep merging the sets if they are connected till you can't merge anymore. If two points aren't in the same set, there's no connection and you don't have to do a search. And you only have to update your sets when network topology changes.
 

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
That's what I was suggesting connected components for. You have a set for every node and keep merging the sets if they are connected till you can't merge anymore. If two points aren't in the same set, there's no connection and you don't have to do a search. And you only have to update your sets when network topology changes.
Which means recalculating the entire network as soon as anyone places or breaks a repeater, allowing people to crash the server with repeaters and autonomous activators.
 

Veggetossj

New Member
Jul 29, 2019
245
0
0
I have been planning a battery of sorts, and this is an interesting idea. How would it manage confined spaces?
Arent the crystals that look like AE2 quartz crystals the batteries? In the video it shows that they can hold the different types of crystal energy.
 
Last edited:

JOBGG

New Member
Jul 29, 2019
62
0
0
You only need to recalc a part of it though. If you have two disjoint sets and you place a connecting repeater, you join the sets, if you remove the repeater you'll...proably have to recalc, yes. I'm slowly running out of applicable ideas, i might not be able to help you with this. I'm not an expert on algorithms though, you might want to put that question on CS stack exchange or something, they might know how to optimize something like that.
 

xTordX

New Member
Jul 29, 2019
576
-6
1
It's like a battery which you can use to take "energy" from a "battery" and move it to another one or fuel special items with it.
 

SkeletonPunk

New Member
Jul 29, 2019
2,063
-3
1
It seems like Chromaticraft requires Rotarycraft, whenever I try and install it I get this:
There was a severe problem during mod loading that has caused the game to fail

cpw.mods.fml.common.LoaderException: java.lang.NoClassDefFoundError: Reika/RotaryCraft/RotaryCraft
 

Oblek1

New Member
Jul 29, 2019
2
0
0
I have a technical problem with ChromatiCraft that I would like to see if anyone has a solution to:

For those unfamiliar with the transmission mechanics of ChromatiCraft:

The pylons are the sources of energy, which can transmit it to receivers. Things like the Casting and Ritual tables, as well as some "powered" blocks, are examples of receivers. As both the pylons and the receivers have a limited range, and all connections must have a clear line of sight, repeaters (which have their own range limit) are almost always necessary to "relay" the energy.

For performance reasons, the location and status of all network tiles (sources, receivers, and repeaters) are cached.

From a more technical side, here is what happens when a request is made to the network:

The networker logs a request from a given location, with a specified color, range, and transmission amount. The network then scans over the cache of tiles, collecting only repeaters and sources, and only those within range, and capable of transmitting that color. It then checks each of them to see if there is a clean line of sight. If so, it moves to that location and repeats the process, hopefully eventually finding a source. If no source is found after exhausting all capable those collected repeaters, or there are no operational repeaters of that color within range, it "steps back" to the previous location and tries the next repeater on that level of the list.

If it finds a source, that path is cached for future requests of that color from the original receiver (thus ridding the need of a recalculation for that location unless the network changes) and returned for additional logic.

(More programming-minded users will note that this is a fairly standard recursive search algorithm, and those following my mods' code will notice that this is very similar to ElectriCraft network pathing logic.).

Here is the problem:

With very large (hundreds of repeaters) networks that nonetheless cannot transmit certain colors to the requesting location, any such requests to that network become computationally expensive, as the search tries to exhaust every routing possibility yet never being satisfied. This manifests itself as a significant lag spike that if repeated frequently can see a server time out all of its players.

Compounding this is that the "find nearby repeaters and sources" logic runs over the entire cache of tiles every step, because as far as I can tell it is not possible for the cache to be presorted for every request location.

Here is the network in question. Pylons are denoted with solid circles of their color, while connected ones also have a box around them. Dotted lines roughly represent repeater trails.

Not sure if this would work because it's been a fat minute since I've coded anything, but assuming there's a max range from the request that a source pylon could be (i.e. you search the network but it's hard-capped to stop searching 1k blocks away or w/e) you might consider attempting to path from the source to the request rather than request to the source. Instead of checking every branch it could possibly just look for paths that move the signal closer to the request. So maybe something akin to:

if newPylonSourceDistance < currentPylonSourceDistance then
Move to new pylon
else
Arbitrary pylon in the search like it's programmed now

Idk that this method necessarily completely solves the problem so much as it might cut down on the number of necessary searches at least? Like I said it's been a bit since I've programmed so I don't know if this is applicable to the way you've cached your data but thought I'd let you chew on it.

P.S. Excited for the v3 update ^_^
 

EyeDeck

Well-Known Member
Apr 16, 2013
236
87
54
The way I think I would approach the transmission issue would be a bit different from how it's done now.

First, currently all pylons are added to the same cache that is scanned over each time a repeater jump occurs on pylon generation, right? A quick optimization would be to remove all pylons from the cache until a receiver or (edit: pylon) repeater is placed within range of it. Removing a receiver in range of a pylon would check the nearby pylon for any other valid receivers in its radius, and if none are found, remove the pylon from the cache again. This should massively reduce the performance hit caused by a large map.

Second, unrelated to the first, and which would be a lot more technically difficult to implement, would involve creating a separate network cache (that would also store source energy status) for each individual network.
  1. Upon repeater placement, it would scan a radius (e.g. +/-10 blocks on x,y and z, or whatever the max range is set to) for nearby sources and repeaters, and store them in memory.
  2. If one repeater, or multiple repeaters on the same network, are found, the new repeater is added to the other repeater's network.
  3. If multiple repeaters on separate networks are found, the other networks are merged and the new repeater is added to the merged network.
  4. If no other repeaters are found, a new network is created.
  5. If a source is found, the source is added to the network, and the source's charge status is added to the network.
I am unsure how to handle splitting networks when a repeater is removed. The only way I can think to handle this efficiently is, upon repeater removal, to sort every node on that repeater's network into a minimum spanning tree, check every edge length, and if any edge weight now exceeds Chromaticraft's maximum connectivity distance, split the network on that edge.

At this point, when a request from a receiver is made, it can either:
Do a block search in a radius, looking for valid repeaters, then check if the network that repeater is on has access to enough of the relevant color to fulfill the request.
OR
Sort through each network of the relevant color from the network cache, check if that network has access to enough of the relevant color to fulfill the request and, if so, check if any node on that network is within range of the receiver.
Chromaticraft can then proceed as normal, except limiting its search for valid repeater jumps to only the nodes on the network of the first repeater.
 
Last edited:

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
The way I think I would approach the transmission issue would be a bit different from how it's done now.

First, currently all pylons are added to the same cache that is scanned over each time a repeater jump occurs on pylon generation, right? A quick optimization would be to remove all pylons from the cache until a receiver or pylon is placed within range of it. Removing a receiver in range of a pylon would check the nearby pylon for any other valid receivers in its radius, and if none are found, remove the pylon from the cache again. This should massively reduce the performance hit caused by a large map.

Second, unrelated to the first, and which would be a lot more technically difficult to implement, would involve creating a separate network cache (that would also store source energy status) for each individual network.
  1. Upon repeater placement, it would scan a radius (e.g. +/-10 blocks on x,y and z, or whatever the max range is set to) for nearby sources and repeaters, and store them in memory.
  2. If one repeater, or multiple repeaters on the same network, are found, the new repeater is added to the other repeater's network.
  3. If multiple repeaters on separate networks are found, the other networks are merged and the new repeater is added to the merged network.
  4. If no other repeaters are found, a new network is created.
  5. If a source is found, the source is added to the network, and the source's charge status is added to the network.
I am unsure how to handle splitting networks when a repeater is removed. The only way I can think to handle this efficiently is, upon repeater removal, to sort every node on that repeater's network into a minimum spanning tree, check every edge length, and if any edge weight now exceeds Chromaticraft's maximum connectivity distance, split the network on that edge.

At this point, when a request from a receiver is made, it can either:
Do a block search in a radius, looking for valid repeaters, then check if the network that repeater is on has access to enough of the relevant color to fulfill the request.
OR
Sort through each network of the relevant color from the network cache, check if that network has access to enough of the relevant color to fulfill the request and, if so, check if any node on that network is within range of the receiver.
Chromaticraft can then proceed as normal, except limiting its search for valid repeater jumps to only the nodes on the network of the first repeater.
I tried a per-repeater cache. It actually made the performance far worse.


@Pyure
 
  • Like
Reactions: Celestialphoenix

EyeDeck

Well-Known Member
Apr 16, 2013
236
87
54
I tried a per-repeater cache. It actually made the performance far worse.
I was not suggesting a per-repeater cache, I was suggesting a cache on the network level; a method to partition off separate networks, and also solve the issue with large networks without a valid source.

I will admit, I'm not sure how much calculation would be required each time a repeater is added or removed. I don't think the entire network would need to be recalculated when a repeater would be placed, and nearby repeaters could be looked up from the global cache, which should be fairly cheap. Removing a repeater, however, would require significant calculation, which may introduce the autonomous activator attack you mentioned earlier depending on how complex it would be in practice.
 
Last edited: