aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/graphs/PowerNodes.java
blob: 411d690cca99ce69b9ef2213347d131b8b35a892 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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
    static public int powerNode(Node aCurrentNode, Node aPreviousNode, NodeList aConsumers, int aVoltage, int aMaxAmps) {
        int 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++) {
                    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,false);
                            tConsumer =(ConsumerNode) aConsumers.getNextNode();
                            break;
                        } 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--) {
                    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,true);
                        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 int powerNodeAbove(Node aCurrentNode, Node aPreviousNode, NodeList aConsumers, int aVoltage, int aMaxAmps) {
        int 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--) {
                    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,true);
                        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 int processNextNode(Node aCurrentNode, Node aNextNode, NodeList aConsumers, int aSide, int aMaxAmps, int aVoltage) {
        PowerNodePath tPath = (PowerNodePath)aCurrentNode.mNodePaths[aSide];
        PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
        int tVoltLoss = 0;
        if (tSelfPath != null) {
            tVoltLoss += tSelfPath.getLoss();
            tSelfPath.applyVoltage(aVoltage,false);
        }
        tPath.applyVoltage(aVoltage - tVoltLoss,true);
        tVoltLoss += tPath.getLoss();
        int tAmps = powerNode(aNextNode,aCurrentNode,aConsumers,aVoltage - tVoltLoss,aMaxAmps );
        tPath.addAmps(tAmps);
        if (tSelfPath != null)
            tSelfPath.addAmps(tAmps);
        return tAmps;
    }

    protected static int processNextNodeAbove(Node aCurrentNode, Node aNextNode, NodeList aConsumers, int aSide, int aMaxAmps, int aVoltage) {
        PowerNodePath tPath = (PowerNodePath)aCurrentNode.mNodePaths[aSide];
        PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
        int tVoltLoss = 0;
        if (tSelfPath != null) {
            tVoltLoss += tSelfPath.getLoss();
            tSelfPath.applyVoltage(aVoltage,false);
        }
        tPath.applyVoltage(aVoltage - tVoltLoss,true);
        tVoltLoss += tPath.getLoss();
        int tAmps = powerNodeAbove(aNextNode,aCurrentNode,aConsumers,aVoltage - tVoltLoss,aMaxAmps );
        tPath.addAmps(tAmps);
        if (tSelfPath != null)
            tSelfPath.addAmps(tAmps);
        return tAmps;
    }

    protected static int processNodeInject(Node aCurrentNode, ConsumerNode aConsumer, int aSide,int aMaxAmps, int aVoltage,
                                           boolean isUp) {
        PowerNodePath tPath = (PowerNodePath)aCurrentNode.mNodePaths[aSide];
        PowerNodePath tSelfPath = (PowerNodePath) aCurrentNode.mSelfPath;
        int tVoltLoss = 0;
        if (tSelfPath != null) {
            tVoltLoss += tSelfPath.getLoss();
            tSelfPath.applyVoltage(aVoltage,false);
        }
        tPath.applyVoltage(aVoltage - tVoltLoss,true);
        tVoltLoss += tPath.getLoss();
        int tAmps = aConsumer.injectEnergy(aVoltage - tVoltLoss,aMaxAmps);
        tPath.addAmps(tAmps);
        if (tSelfPath != null)
            tSelfPath.addAmps(tAmps);
        return tAmps;
    }
}