aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/graphs/PowerNodes.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api/graphs/PowerNodes.java')
-rw-r--r--src/main/java/gregtech/api/graphs/PowerNodes.java182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/graphs/PowerNodes.java b/src/main/java/gregtech/api/graphs/PowerNodes.java
new file mode 100644
index 0000000000..98d35e2971
--- /dev/null
+++ b/src/main/java/gregtech/api/graphs/PowerNodes.java
@@ -0,0 +1,182 @@
+package gregtech.api.graphs;
+
+import gregtech.api.graphs.consumers.ConsumerNode;
+import gregtech.api.graphs.paths.PowerNodePath;
+
+/*
+ * look for and power node that need power how this works a node only contains nodes that has a higher value then it
+ * self except for 1 which is the return node this node also contains the highest known node value of its network this
+ * network only includes nodes that have a higher value then it self so it does not know the highest known value that
+ * the return node knows with these rules we can know for the target node to be in the network of a node, the target
+ * node must have a value no less than the node we are looking and no greater than the highest value that node knows
+ * this way we don't have to go over the entire network to look for it we also hold a list of all consumers so we can
+ * check before looking if that consumer actually needs power and only look for nodes that actually need power
+ */
+public class PowerNodes {
+
+ // check if the looked for node is next to or get the next node that is closer to it
+ public static long powerNode(Node aCurrentNode, Node aPreviousNode, NodeList aConsumers, long aVoltage,
+ long aMaxAmps) {
+ long tAmpsUsed = 0;
+ ConsumerNode tConsumer = (ConsumerNode) aConsumers.getNode();
+ int tLoopProtection = 0;
+ while (tConsumer != null) {
+ int tTargetNodeValue = tConsumer.mNodeValue;
+ // if the target node has a value less then the current node
+ if (tTargetNodeValue < aCurrentNode.mNodeValue || tTargetNodeValue > aCurrentNode.mHighestNodeValue) {
+ for (int j = 0; j < 6; j++) {
+ final Node tNextNode = aCurrentNode.mNeighbourNodes[j];
+ if (tNextNode != null && tNextNode.mNodeValue < aCurrentNode.mNodeValue) {
+ if (tNextNode.mNodeValue == tConsumer.mNodeValue) {
+ tAmpsUsed += processNodeInject(aCurrentNode, tConsumer, j, aMaxAmps - tAmpsUsed, aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNextNode();
+ } else {
+ if (aPreviousNode == tNextNode) return tAmpsUsed;
+ tAmpsUsed += processNextNode(
+ aCurrentNode,
+ tNextNode,
+ aConsumers,
+ j,
+ aMaxAmps - tAmpsUsed,
+ aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNode();
+ }
+ break;
+ }
+ }
+ } else {
+ // if the target node has a node value greater then current node value
+ for (int side = 5; side > -1; side--) {
+ final Node tNextNode = aCurrentNode.mNeighbourNodes[side];
+ if (tNextNode == null) continue;
+ if (tNextNode.mNodeValue > aCurrentNode.mNodeValue && tNextNode.mNodeValue < tTargetNodeValue) {
+ if (tNextNode == aPreviousNode) return tAmpsUsed;
+ tAmpsUsed += processNextNodeAbove(
+ aCurrentNode,
+ tNextNode,
+ aConsumers,
+ side,
+ aMaxAmps - tAmpsUsed,
+ aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNode();
+ break;
+ } else if (tNextNode.mNodeValue == tTargetNodeValue) {
+ tAmpsUsed += processNodeInject(aCurrentNode, tConsumer, side, aMaxAmps - tAmpsUsed, aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNextNode();
+ break;
+ }
+ }
+ }
+ if (aMaxAmps - tAmpsUsed <= 0) {
+ return tAmpsUsed;
+ }
+ if (tLoopProtection++ > 20) {
+ throw new NullPointerException("infinite loop in powering nodes ");
+ }
+ }
+ return tAmpsUsed;
+ }
+
+ // checking if target node is next to it or has a higher value then current node value
+ // these functions are different to either go down or up the stack
+ protected static long powerNodeAbove(Node aCurrentNode, Node aPreviousNode, NodeList aConsumers, long aVoltage,
+ long aMaxAmps) {
+ long tAmpsUsed = 0;
+ int tLoopProtection = 0;
+ ConsumerNode tConsumer = (ConsumerNode) aConsumers.getNode();
+ while (tConsumer != null) {
+ int tTargetNodeValue = tConsumer.mNodeValue;
+ if (tTargetNodeValue > aCurrentNode.mHighestNodeValue || tTargetNodeValue < aCurrentNode.mNodeValue) {
+ return tAmpsUsed;
+ } else {
+ for (int side = 5; side > -1; side--) {
+ final Node tNextNode = aCurrentNode.mNeighbourNodes[side];
+ if (tNextNode == null) continue;
+ if (tNextNode.mNodeValue > aCurrentNode.mNodeValue && tNextNode.mNodeValue < tTargetNodeValue) {
+ if (tNextNode == aPreviousNode) return tAmpsUsed;
+ tAmpsUsed += processNextNodeAbove(
+ aCurrentNode,
+ tNextNode,
+ aConsumers,
+ side,
+ aMaxAmps - tAmpsUsed,
+ aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNode();
+ break;
+ } else if (tNextNode.mNodeValue == tTargetNodeValue) {
+ tAmpsUsed += processNodeInject(aCurrentNode, tConsumer, side, aMaxAmps - tAmpsUsed, aVoltage);
+ tConsumer = (ConsumerNode) aConsumers.getNextNode();
+ break;
+ }
+ }
+ }
+ if (aMaxAmps - tAmpsUsed <= 0) {
+ return tAmpsUsed;
+ }
+ if (tLoopProtection++ > 20) {
+ throw new NullPointerException("infinite loop in powering nodes ");
+ }
+ }
+ return tAmpsUsed;
+ }
+
+ protected static long processNextNode(Node aCurrentNode, Node aNextNode, NodeList aConsumers, int ordinalSide,
+ long aMaxAmps, long aVoltage) {
+ if (aCurrentNode.locks[ordinalSide].isLocked()) {
+ aConsumers.getNextNode();
+ return 0;
+ }
+ final PowerNodePath tPath = (PowerNodePath) aCurrentNode.mNodePaths[ordinalSide];
+ final PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
+ long tVoltLoss = 0;
+ if (tSelfPath != null) {
+ tVoltLoss += tSelfPath.getLoss();
+ tSelfPath.applyVoltage(aVoltage, false);
+ }
+ tPath.applyVoltage(aVoltage - tVoltLoss, true);
+ tVoltLoss += tPath.getLoss();
+ long tAmps = powerNode(aNextNode, aCurrentNode, aConsumers, aVoltage - tVoltLoss, aMaxAmps);
+ tPath.addAmps(tAmps);
+ if (tSelfPath != null) tSelfPath.addAmps(tAmps);
+ return tAmps;
+ }
+
+ protected static long processNextNodeAbove(Node aCurrentNode, Node aNextNode, NodeList aConsumers, int ordinalSide,
+ long aMaxAmps, long aVoltage) {
+ if (aCurrentNode.locks[ordinalSide].isLocked()) {
+ aConsumers.getNextNode();
+ return 0;
+ }
+ final PowerNodePath tPath = (PowerNodePath) aCurrentNode.mNodePaths[ordinalSide];
+ final PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
+ long tVoltLoss = 0;
+ if (tSelfPath != null) {
+ tVoltLoss += tSelfPath.getLoss();
+ tSelfPath.applyVoltage(aVoltage, false);
+ }
+ tPath.applyVoltage(aVoltage - tVoltLoss, true);
+ tVoltLoss += tPath.getLoss();
+ long tAmps = powerNodeAbove(aNextNode, aCurrentNode, aConsumers, aVoltage - tVoltLoss, aMaxAmps);
+ tPath.addAmps(tAmps);
+ if (tSelfPath != null) tSelfPath.addAmps(tAmps);
+ return tAmps;
+ }
+
+ protected static long processNodeInject(Node aCurrentNode, ConsumerNode aConsumer, int ordinalSide, long aMaxAmps,
+ long aVoltage) {
+ if (aCurrentNode.locks[ordinalSide].isLocked()) return 0;
+ final PowerNodePath tPath = (PowerNodePath) aCurrentNode.mNodePaths[ordinalSide];
+ final PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
+ long tVoltLoss = 0;
+ if (tSelfPath != null) {
+ tVoltLoss += tSelfPath.getLoss();
+ tSelfPath.applyVoltage(aVoltage, false);
+ }
+ tPath.applyVoltage(aVoltage - tVoltLoss, true);
+ tVoltLoss += tPath.getLoss();
+ long tAmps = aConsumer.injectEnergy(aVoltage - tVoltLoss, aMaxAmps);
+ tPath.addAmps(tAmps);
+ if (tSelfPath != null) tSelfPath.addAmps(tAmps);
+ return tAmps;
+ }
+}