diff options
Diffstat (limited to 'src')
22 files changed, 1007 insertions, 14 deletions
diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java index e24297c48c..ba7e3ab43e 100644 --- a/src/main/java/gregtech/api/GregTech_API.java +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -17,6 +17,7 @@ import gregtech.api.objects.GT_Cover_Default; import gregtech.api.objects.GT_Cover_None; import gregtech.api.objects.GT_HashSet; import gregtech.api.objects.GT_ItemStack; +import gregtech.api.threads.GT_Runnable_Cable_Update; import gregtech.api.threads.GT_Runnable_MachineBlockUpdate; import gregtech.api.util.*; import gregtech.api.world.GT_Worldgen; @@ -407,6 +408,15 @@ public class GregTech_API { return false; } + public static boolean causeCableUpdate(World aWorld, int aX, int aY, int aZ) { + if (aWorld != null && !aWorld.isRemote) { // World might be null during Worldgen + GT_Runnable_Cable_Update.setCableUpdateValues(aWorld, new ChunkCoordinates(aX, aY, aZ)); + return true; + } + return false; + + } + /** * Adds a Multi-Machine Block, like my Machine Casings for example. * You should call @causeMachineUpdate in @Block.breakBlock and in @Block.onBlockAdded of your registered Block. diff --git a/src/main/java/gregtech/api/graphs/GenerateNodeMap.java b/src/main/java/gregtech/api/graphs/GenerateNodeMap.java new file mode 100644 index 0000000000..c5b60471de --- /dev/null +++ b/src/main/java/gregtech/api/graphs/GenerateNodeMap.java @@ -0,0 +1,174 @@ +package gregtech.api.graphs; + +import gregtech.api.graphs.consumers.ConsumerNode; +import gregtech.api.graphs.paths.NodePath; +import gregtech.api.metatileentity.*; +import net.minecraft.tileentity.TileEntity; + +import java.util.ArrayList; +import java.util.HashSet; + +import static gregtech.api.util.GT_Utility.getOppositeSide; + + +//generates the node map +abstract public class GenerateNodeMap { + //clearign the node map to make sure it is gone on reset + public static void clearNodeMap(Node aNode,int aReturnNodeValue) { + if (aNode.mTileEntity instanceof BaseMetaPipeEntity) { + BaseMetaPipeEntity tPipe = (BaseMetaPipeEntity) aNode.mTileEntity; + tPipe.setNode(null); + tPipe.setNodePath(null); + if (aNode.mSelfPath != null) { + aNode.mSelfPath.clearPath(); + aNode.mSelfPath = null; + } + } + for (int i = 0;i<6;i++) { + NodePath tPath = aNode.mNodePats[i]; + if (tPath != null) { + tPath.clearPath(); + aNode.mNodePats[i] = null; + } + Node tNextNode = aNode.mNeigbourNodes[i]; + if (tNextNode == null) continue; + if (tNextNode.mNodeValue != aReturnNodeValue) + clearNodeMap(tNextNode,aNode.mNodeValue); + aNode.mNeigbourNodes[i] = null; + } + } + + //gets the next node + protected void generateNextNode(BaseMetaPipeEntity aPipe, Node aPipeNode, int aInvalidSide, int aNextNodeVale, + ArrayList<ConsumerNode> tConsumers, HashSet<Node> tNodeMap) { + MetaPipeEntity tMetaPipe = (MetaPipeEntity) aPipe.getMetaTileEntity(); + for (byte i = 0;i<6;i++) { + if (i==aInvalidSide) { + continue; + } + TileEntity tNextTileEntity = aPipe.getTileEntityAtSide(i); + if (tNextTileEntity == null || (tMetaPipe != null && !tMetaPipe.isConnectedAtSide(i))) continue; + ArrayList<MetaPipeEntity> tNewPipes = new ArrayList<MetaPipeEntity>(); + Pair nextTileEntity = getNextValidTileEntity(tNextTileEntity,tNewPipes,i,tNodeMap); + if (nextTileEntity != null) { + Node tNextNode = generateNode(nextTileEntity.mTileEntity,aPipeNode,aNextNodeVale+1,tNewPipes, + nextTileEntity.mSide,tConsumers,tNodeMap); + if (tNextNode != null) { + aNextNodeVale = tNextNode.mHigestNodeValue; + aPipeNode.mHigestNodeValue = tNextNode.mHigestNodeValue; + aPipeNode.mNeigbourNodes[i] = tNextNode; + aPipeNode.mNodePats[i] = aPipeNode.mReturnPath; + } + } + } + } + + //on a valid tilentity create a new node + protected Node generateNode(TileEntity aTileEntity, Node aPreviousNode, int aNextNodeVale, ArrayList<MetaPipeEntity> aPipes, + int aSide, ArrayList<ConsumerNode> aConsumers, HashSet<Node> aNodeMap) { + if (aTileEntity.isInvalid()) return null; + int tSideOp = getOppositeSide(aSide); + int tInvalidSide = aPreviousNode == null ? -1 : tSideOp; + Node tThisNode = null; + if (isPipe(aTileEntity)){ + BaseMetaPipeEntity tPipe = (BaseMetaPipeEntity) aTileEntity; + MetaPipeEntity tMetaPipe = (MetaPipeEntity) tPipe.getMetaTileEntity(); + int tConections = getNumberOfConections(tMetaPipe); + Node tPipeNode; + if (tConections == 1) { + tPipeNode = getEmptyNode(aNextNodeVale,tSideOp,aTileEntity,aConsumers); + if (tPipeNode == null) return null; + } else { + tPipeNode = getPipeNode(aNextNodeVale,tSideOp,aTileEntity,aConsumers); + } + tPipe.setNode(tPipeNode); + aNodeMap.add(tPipeNode); + tPipeNode.mSelfPath = getNewPath(new MetaPipeEntity[]{tMetaPipe}); + tThisNode = tPipeNode; + if (tInvalidSide>0) { + tPipeNode.mNeigbourNodes[tInvalidSide] = aPreviousNode; + tPipeNode.mNodePats[tInvalidSide] = getNewPath(aPipes.toArray(new MetaPipeEntity[0])); + aPreviousNode.mReturnPath = tPipeNode.mNodePats[tInvalidSide]; + } + if (tConections > 1) + generateNextNode(tPipe,tPipeNode,tInvalidSide,aNextNodeVale,aConsumers,aNodeMap); + } else if (addConsumer(aTileEntity,tSideOp,aNextNodeVale,aConsumers)) { + ConsumerNode tConsumeNode = aConsumers.get(aConsumers.size()-1); + tConsumeNode.mNeigbourNodes[tSideOp] = aPreviousNode; + tConsumeNode.mNodePats[tSideOp] = getNewPath(aPipes.toArray(new MetaPipeEntity[0])); + aPreviousNode.mReturnPath = tConsumeNode.mNodePats[tSideOp]; + tThisNode = tConsumeNode; + } + return tThisNode; + } + + //go over the pipes until we see a valid tileentity that needs a node + protected Pair getNextValidTileEntity(TileEntity aTileEntity, ArrayList<MetaPipeEntity> aPipes, int aSide, HashSet<Node> aNodeMap) { + if (isPipe(aTileEntity)) { + BaseMetaPipeEntity tPipe = (BaseMetaPipeEntity) aTileEntity; + MetaPipeEntity tMetaPipe = (MetaPipeEntity) tPipe.getMetaTileEntity(); + Node tNode = tPipe.getNode(); + if (tNode != null) { + if (aNodeMap.contains(tNode)) + return null; + } + int tConections = getNumberOfConections(tMetaPipe); + if (tConections == 2) { + int tSideOp = getOppositeSide(aSide); + for (byte i = 0;i<6;i++) { + if (i == tSideOp || !(tMetaPipe.isConnectedAtSide(i))) continue; + TileEntity tNewTileEntity = tPipe.getTileEntityAtSide(i); + if (tNewTileEntity == null) continue; + if (isPipe(tNewTileEntity)) { + aPipes.add(tMetaPipe); + return getNextValidTileEntity(tNewTileEntity,aPipes,i,aNodeMap); + } else { + return new Pair(aTileEntity,i); + } + } + } else { + return new Pair(aTileEntity,aSide); + } + } else { + return new Pair(aTileEntity,aSide); + } + return null; + } + + private class Pair { + public int mSide; + public TileEntity mTileEntity; + public Pair(TileEntity aTileEntity, int aSide) { + this.mTileEntity = aTileEntity; + this.mSide = aSide; + } + } + + //if check if the tileentity is the correct pipe + protected boolean isPipe(TileEntity aTileEntity) { + return aTileEntity instanceof BaseMetaPipeEntity; + } + //checks if the tileentity is a consumer and add to the list + abstract protected boolean addConsumer(TileEntity aTileEntity, int aSide, int aNodeValue, ArrayList<ConsumerNode> aConsumers); + //get correct pathClass that you need for your node network + protected abstract NodePath getNewPath(MetaPipeEntity[] aPipes); + + //used for if you need to use death ends for somthing + //can be null + protected Node getEmptyNode(int aNodeValue, int aSide, TileEntity aTileEntity, ArrayList<ConsumerNode> aConsumers) { + return null; + } + //get correct node type you need for your network + protected Node getPipeNode(int aNodeValue, int aSide, TileEntity aTileEntity, ArrayList<ConsumerNode> aConsumers) { + return new Node(aNodeValue,aTileEntity,aConsumers); + } + + //get how many conections the pipe have + private static int getNumberOfConections(MetaPipeEntity aPipe) { + int tCons = 0; + for (int i = 0; i < 6; i++) { + if (aPipe.isConnectedAtSide(i)) tCons++; + } + return tCons; + } +} diff --git a/src/main/java/gregtech/api/graphs/GenerateNodeMapPower.java b/src/main/java/gregtech/api/graphs/GenerateNodeMapPower.java new file mode 100644 index 0000000000..41de33080c --- /dev/null +++ b/src/main/java/gregtech/api/graphs/GenerateNodeMapPower.java @@ -0,0 +1,81 @@ +package gregtech.api.graphs; + +import cofh.api.energy.IEnergyReceiver; +import gregtech.api.GregTech_API; +import gregtech.api.graphs.consumers.*; +import gregtech.api.graphs.paths.NodePath; +import gregtech.api.graphs.paths.PowerNodePath; +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.BaseMetaTileEntity; +import gregtech.api.metatileentity.MetaPipeEntity; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; +import ic2.api.energy.tile.IEnergySink; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; + +import java.util.ArrayList; +import java.util.HashSet; + +//node map generator for power distrubution +public class GenerateNodeMapPower extends GenerateNodeMap { + public GenerateNodeMapPower(BaseMetaPipeEntity aTileEntity) { + generateNode(aTileEntity,null,1,null, + -1,new ArrayList<>(),new HashSet<>()); + } + + @Override + protected boolean isPipe(TileEntity aTileEntity) { + return super.isPipe(aTileEntity) && ((BaseMetaPipeEntity) aTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable; + } + + @Override + protected NodePath getNewPath(MetaPipeEntity[] aPipes) { + return new PowerNodePath(aPipes); + } + + //used to apply voltage on death ends + @Override + protected Node getEmptyNode(int aNodeValue, int aSide, TileEntity aTileEntity, ArrayList<ConsumerNode> aConsumers) { + Node tNode = new EmptyPowerConsumer(aNodeValue, aTileEntity, aSide, aConsumers); + aConsumers.add((ConsumerNode) tNode); + return tNode; + } + + @Override + protected Node getPipeNode(int aNodeValue, int aSide, TileEntity aTileEntity, ArrayList<ConsumerNode> aConsumers) { + return new PowerNode(aNodeValue, aTileEntity, aConsumers); + } + + @Override + protected boolean addConsumer(TileEntity aTileEntity, int aSide, int aNodeValue, ArrayList<ConsumerNode> aConsumers) { + if (aTileEntity instanceof BaseMetaTileEntity) { + BaseMetaTileEntity tBaseTileEntity = (BaseMetaTileEntity) aTileEntity; + if (tBaseTileEntity.inputEnergyFrom((byte) aSide,false)) { + ConsumerNode tConsumerNode = new NodeGTBaseMetaTile(aNodeValue,tBaseTileEntity, aSide, aConsumers); + aConsumers.add(tConsumerNode); + return true; + } + } else if (aTileEntity instanceof IEnergySink) { + //ic2 wants the tilentitty next to it of that side not going to add a bunch of arguments just for ic2 + //crossborder checks to not not load chuncks just to make sure + int dX = aTileEntity.xCoord + ForgeDirection.getOrientation(aSide).offsetX; + int dY = aTileEntity.yCoord + ForgeDirection.getOrientation(aSide).offsetY; + int dZ = aTileEntity.zCoord + ForgeDirection.getOrientation(aSide).offsetZ; + boolean crossesChuncks = dX >> 4 != aTileEntity.xCoord >> 4 || dZ >> 4 != aTileEntity.zCoord >> 4; + TileEntity tNextTo = null; + if (!crossesChuncks || !aTileEntity.getWorldObj().blockExists(dX, dY, dZ)) + tNextTo = aTileEntity.getWorldObj().getTileEntity(dX, dY, dZ); + + if (((IEnergySink) aTileEntity).acceptsEnergyFrom(tNextTo, ForgeDirection.getOrientation(aSide))) { + ConsumerNode tConsumerNode = new NodeEnergySink(aNodeValue,(IEnergySink) aTileEntity, aSide, aConsumers); + aConsumers.add(tConsumerNode); + return true; + } + } else if (GregTech_API.mOutputRF && aTileEntity instanceof IEnergyReceiver) { + ConsumerNode tConsumerNode = new NodeEnergyReceiver(aNodeValue,(IEnergyReceiver) aTileEntity, aSide, aConsumers); + aConsumers.add(tConsumerNode); + return true; + } + return false; + } +} diff --git a/src/main/java/gregtech/api/graphs/Node.java b/src/main/java/gregtech/api/graphs/Node.java new file mode 100644 index 0000000000..fed599881c --- /dev/null +++ b/src/main/java/gregtech/api/graphs/Node.java @@ -0,0 +1,30 @@ +package gregtech.api.graphs; + +import gregtech.api.graphs.consumers.ConsumerNode; +import gregtech.api.graphs.paths.NodePath; +import net.minecraft.server.MinecraftServer; +import net.minecraft.tileentity.TileEntity; +import java.util.ArrayList; + +//base Node class +public class Node { + public Node(int aNodeValue,TileEntity aTileEntity,ArrayList<ConsumerNode> aConsumers){ + this.mNodeValue = aNodeValue; + this.mTileEntity = aTileEntity; + this.mConsumers = aConsumers; + mHigestNodeValue = aNodeValue; + //you dont want to generate map multiple times in the same tick + mCreationTime = MinecraftServer.getServer().getTickCounter(); + } + + + public int mCreationTime; + public NodePath mSelfPath; + public ArrayList<ConsumerNode> mConsumers; + public int mNodeValue; + public final TileEntity mTileEntity; + public Node[] mNeigbourNodes = new Node[6]; + public NodePath[] mNodePats = new NodePath[6]; + public NodePath mReturnPath; + public int mHigestNodeValue; +} diff --git a/src/main/java/gregtech/api/graphs/NodeList.java b/src/main/java/gregtech/api/graphs/NodeList.java new file mode 100644 index 0000000000..702e8446c0 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/NodeList.java @@ -0,0 +1,24 @@ +package gregtech.api.graphs; + +//keep track on wich node is being looked for accrouse the recursif functions +public class NodeList { + Node[] mNodes; + int mConter = 0; + public NodeList(Node[] mNodes) { + this.mNodes = mNodes; + } + + Node getNextNode() { + if (++mConter < mNodes.length) + return mNodes[mConter]; + else + return null; + } + + Node getNode() { + if (mConter < mNodes.length) + return mNodes[mConter]; + else + return null; + } +} diff --git a/src/main/java/gregtech/api/graphs/PowerNode.java b/src/main/java/gregtech/api/graphs/PowerNode.java new file mode 100644 index 0000000000..a92e3ea0ca --- /dev/null +++ b/src/main/java/gregtech/api/graphs/PowerNode.java @@ -0,0 +1,14 @@ +package gregtech.api.graphs; + +import gregtech.api.graphs.consumers.ConsumerNode; +import net.minecraft.tileentity.TileEntity; + +import java.util.ArrayList; + +//base node for power networks +public class PowerNode extends Node{ + public boolean mHadVoltage = false; + public PowerNode(int aNodeValue, TileEntity aTileEntity, ArrayList<ConsumerNode> aConsumers) { + super(aNodeValue, aTileEntity, aConsumers); + } +} 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..39844bdd17 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/PowerNodes.java @@ -0,0 +1,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 what a node contains the target node in its network as long the target node has a value + * more or equal then the node we are looking but is less or equal then the highest value that node knows + * this way we don't have to go over the entire network too 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 tTagetNodeValue = tConsumer.mNodeValue; + //if the target node has a value less then the current node + if (tTagetNodeValue < aCurrentNode.mNodeValue || tTagetNodeValue > aCurrentNode.mHigestNodeValue) { + for (int j = 0;j<6;j++) { + Node tNextNode = aCurrentNode.mNeigbourNodes[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 vale + for (int side = 5;side>-1;side--) { + Node tNextNode = aCurrentNode.mNeigbourNodes[side]; + if (tNextNode == null) continue; + if (tNextNode.mNodeValue > aCurrentNode.mNodeValue && tNextNode.mNodeValue < tTagetNodeValue) { + if (tNextNode == aPreviousNode) return tAmpsUsed; + tAmpsUsed += processNextNodeAbove(aCurrentNode,tNextNode,aConsumers,side,aMaxAmps-tAmpsUsed,aVoltage); + tConsumer =(ConsumerNode) aConsumers.getNode(); + break; + } else if (tNextNode.mNodeValue == tTagetNodeValue) { + 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("infinit loop in powering nodes "); + } + } + return tAmpsUsed; + } + + //checking if target node is next to it ot has a higer value then current node value + //thse functions are difrent to eayer 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 tTagetNodeValue = tConsumer.mNodeValue; + if (tTagetNodeValue > aCurrentNode.mHigestNodeValue || tTagetNodeValue < aCurrentNode.mNodeValue) { + return tAmpsUsed; + } else { + for (int side = 5;side>-1;side--) { + Node tNextNode = aCurrentNode.mNeigbourNodes[side]; + if (tNextNode == null) continue; + if (tNextNode.mNodeValue > aCurrentNode.mNodeValue && tNextNode.mNodeValue < tTagetNodeValue) { + if (tNextNode == aPreviousNode) return tAmpsUsed; + tAmpsUsed += processNextNodeAbove(aCurrentNode,tNextNode,aConsumers,side,aMaxAmps-tAmpsUsed,aVoltage); + tConsumer =(ConsumerNode) aConsumers.getNode(); + break; + } else if (tNextNode.mNodeValue == tTagetNodeValue) { + 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("infinit 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.mNodePats[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.mNodePats[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.mNodePats[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; + } +} diff --git a/src/main/java/gregtech/api/graphs/consumers/ConsumerNode.java b/src/main/java/gregtech/api/graphs/consumers/ConsumerNode.java new file mode 100644 index 0000000000..74aa14f5c9 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/consumers/ConsumerNode.java @@ -0,0 +1,23 @@ +package gregtech.api.graphs.consumers; + +import gregtech.api.graphs.Node; +import net.minecraft.tileentity.TileEntity; + +import java.util.ArrayList; + +//node atached to a tileentity that can consume stuff from the network +public class ConsumerNode extends Node { + public int mSide; + public ConsumerNode(int aNodeValue, TileEntity aTileEntity, int aSide, ArrayList<ConsumerNode> aConsumers) { + super(aNodeValue,aTileEntity,aConsumers); + this.mSide = aSide; + } + + public boolean needsEnergy() { + return !mTileEntity.isInvalid(); + } + + public int injectEnergy(int aVoltage, int aMaxApms) { + return 0; + } +} diff --git a/src/main/java/gregtech/api/graphs/consumers/EmptyPowerConsumer.java b/src/main/java/gregtech/api/graphs/consumers/EmptyPowerConsumer.java new file mode 100644 index 0000000000..4961e77daf --- /dev/null +++ b/src/main/java/gregtech/api/graphs/consumers/EmptyPowerConsumer.java @@ -0,0 +1,27 @@ +package gregtech.api.graphs.consumers; + +import gregtech.api.graphs.paths.PowerNodePath; +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import net.minecraft.tileentity.TileEntity; + +import java.util.ArrayList; + +//this is here to aply voltage to death ends +public class EmptyPowerConsumer extends ConsumerNode{ + public EmptyPowerConsumer(int aNodeValue, TileEntity aTileEntity, int aSide, ArrayList<ConsumerNode> aConsumers) { + super(aNodeValue, aTileEntity, aSide, aConsumers); + } + + @Override + public boolean needsEnergy() { + return false; + } + + @Override + public int injectEnergy(int aVoltage, int aMaxApms) { + BaseMetaPipeEntity tPipe = (BaseMetaPipeEntity) mTileEntity; + PowerNodePath tPath =(PowerNodePath) tPipe.getNodePath(); + tPath.applyVoltage(aVoltage,true); + return 0; + } +} diff --git a/src/main/java/gregtech/api/graphs/consumers/NodeEnergyReceiver.java b/src/main/java/gregtech/api/graphs/consumers/NodeEnergyReceiver.java new file mode 100644 index 0000000000..a4ff9c62d8 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/consumers/NodeEnergyReceiver.java @@ -0,0 +1,79 @@ +package gregtech.api.graphs.consumers; + +import cofh.api.energy.IEnergyReceiver; +import gregtech.GT_Mod; +import gregtech.api.GregTech_API; +import gregtech.api.util.GT_Utility; +import gregtech.api.util.WorldSpawnedEventBuilder; +import gregtech.common.GT_Pollution; +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +import java.util.ArrayList; + +import static gregtech.api.enums.GT_Values.V; + +//consumer for RF machines +public class NodeEnergyReceiver extends ConsumerNode { + public NodeEnergyReceiver(int aNodeValue, IEnergyReceiver aTileEntity, int aSide, ArrayList<ConsumerNode> aConsumers) { + super(aNodeValue, (TileEntity) aTileEntity, aSide, aConsumers); + } + + @Override + public int injectEnergy(int aVoltage, int aMaxApms) { + ForgeDirection tDirection = ForgeDirection.getOrientation(mSide); + int rfOut = GT_Utility.safeInt(aVoltage * GregTech_API.mEUtoRF / 100); + if (((IEnergyReceiver) mTileEntity).receiveEnergy(tDirection, rfOut, true) == rfOut) { + ((IEnergyReceiver) mTileEntity).receiveEnergy(tDirection, rfOut, false); + return 1; + } + if (GregTech_API.mRFExplosions && GregTech_API.sMachineExplosions && + ((IEnergyReceiver) mTileEntity).getMaxEnergyStored(tDirection) < rfOut * 600L) { + explode(rfOut); + } + return 0; + } + + //copyed from IEnergyConnected + private void explode(int aRfOut) { + if (aRfOut > 32L * GregTech_API.mEUtoRF / 100L) { + int aExplosionPower = aRfOut; + float tStrength = + aExplosionPower < V[0] ? 1.0F : + aExplosionPower < V[1] ? 2.0F : + aExplosionPower < V[2] ? 3.0F : + aExplosionPower < V[3] ? 4.0F : + aExplosionPower < V[4] ? 5.0F : + aExplosionPower < V[4] * 2 ? 6.0F : + aExplosionPower < V[5] ? 7.0F : + aExplosionPower < V[6] ? 8.0F : + aExplosionPower < V[7] ? 9.0F : + aExplosionPower < V[8] ? 10.0F : + aExplosionPower < V[8] * 2 ? 11.0F : + aExplosionPower < V[9] ? 12.0F : + aExplosionPower < V[10] ? 13.0F : + aExplosionPower < V[11] ? 14.0F : + aExplosionPower < V[12] ? 15.0F : + aExplosionPower < V[12] * 2 ? 16.0F : + aExplosionPower < V[13] ? 17.0F : + aExplosionPower < V[14] ? 18.0F : + aExplosionPower < V[15] ? 19.0F : 20.0F; + int tX = mTileEntity.xCoord, tY = mTileEntity.yCoord, tZ = mTileEntity.zCoord; + World tWorld = mTileEntity.getWorldObj(); + GT_Utility.sendSoundToPlayers(tWorld, GregTech_API.sSoundList.get(209), 1.0F, -1, tX, tY, tZ); + tWorld.setBlock(tX, tY, tZ, Blocks.air); + if (GregTech_API.sMachineExplosions) + if (GT_Mod.gregtechproxy.mPollution) + GT_Pollution.addPollution(tWorld.getChunkFromBlockCoords(tX, tZ), 100000); + + new WorldSpawnedEventBuilder.ExplosionEffectEventBuilder() + .setStrength(tStrength) + .setSmoking(true) + .setPosition(tX + 0.5, tY + 0.5, tZ + 0.5) + .setWorld(tWorld) + .run(); + } + } +} diff --git a/src/main/java/gregtech/api/graphs/consumers/NodeEnergySink.java b/src/main/java/gregtech/api/graphs/consumers/NodeEnergySink.java new file mode 100644 index 0000000000..e315c75d9f --- /dev/null +++ b/src/main/java/gregtech/api/graphs/consumers/NodeEnergySink.java @@ -0,0 +1,28 @@ +package gregtech.api.graphs.consumers; + +import ic2.api.energy.tile.IEnergySink; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; + +import java.util.ArrayList; + +//consumer for IC2 machines +public class NodeEnergySink extends ConsumerNode { + public NodeEnergySink(int nodeValue, IEnergySink tileEntity, int side, ArrayList<ConsumerNode> consumers) { + super(nodeValue, (TileEntity) tileEntity, side, consumers); + } + + @Override + public boolean needsEnergy() { + return super.needsEnergy() && ((IEnergySink) mTileEntity).getDemandedEnergy() > 0; + } + + @Override + public int injectEnergy(int aVoltage, int aMaxApms) { + int tUsedAmps = 0; + while (aMaxApms > tUsedAmps && ((IEnergySink) mTileEntity).getDemandedEnergy() > 0 && + ((IEnergySink) mTileEntity).injectEnergy(ForgeDirection.getOrientation(mSide), aVoltage, aVoltage) < aVoltage) + tUsedAmps++; + return tUsedAmps; + } +} diff --git a/src/main/java/gregtech/api/graphs/consumers/NodeGTBaseMetaTile.java b/src/main/java/gregtech/api/graphs/consumers/NodeGTBaseMetaTile.java new file mode 100644 index 0000000000..1eb562ff68 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/consumers/NodeGTBaseMetaTile.java @@ -0,0 +1,23 @@ +package gregtech.api.graphs.consumers; + +import gregtech.api.interfaces.tileentity.IEnergyConnected; +import gregtech.api.metatileentity.BaseMetaTileEntity; +import java.util.ArrayList; + +//consumer for gt machines +public class NodeGTBaseMetaTile extends ConsumerNode { + public NodeGTBaseMetaTile(int aNodeValue, BaseMetaTileEntity aTileEntity, int aSide, ArrayList<ConsumerNode> aConsumers) { + super(aNodeValue, aTileEntity, aSide, aConsumers); + } + + @Override + public int injectEnergy(int aVoltage, int aMaxApms) { + return (int)((IEnergyConnected) mTileEntity).injectEnergyUnits((byte) mSide,aVoltage, aMaxApms); + } + + @Override + public boolean needsEnergy() { + BaseMetaTileEntity tTileEntity = (BaseMetaTileEntity) mTileEntity; + return super.needsEnergy() && tTileEntity.getStoredEU() < tTileEntity.getEUCapacity(); + } +} diff --git a/src/main/java/gregtech/api/graphs/paths/NodePath.java b/src/main/java/gregtech/api/graphs/paths/NodePath.java new file mode 100644 index 0000000000..ddbd570af3 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/paths/NodePath.java @@ -0,0 +1,29 @@ +package gregtech.api.graphs.paths; + +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.MetaPipeEntity; + +//to contain all info about the path between nodes +public class NodePath { + protected MetaPipeEntity[] mPipes; + + public NodePath(MetaPipeEntity[] aCables) { + this.mPipes = aCables; + processPipes(); + } + + public void clearPath() { + for (int i = 0; i< mPipes.length; i++) { + BaseMetaPipeEntity tBasePipe = (BaseMetaPipeEntity) mPipes[i].getBaseMetaTileEntity(); + if (tBasePipe != null) { + tBasePipe.setNodePath(null); + } + } + } + protected void processPipes() { + for (MetaPipeEntity tPipe : mPipes) { + BaseMetaPipeEntity basePipe = (BaseMetaPipeEntity) tPipe.getBaseMetaTileEntity(); + basePipe.setNodePath(this); + } + } +} diff --git a/src/main/java/gregtech/api/graphs/paths/PowerNodePath.java b/src/main/java/gregtech/api/graphs/paths/PowerNodePath.java new file mode 100644 index 0000000000..7c71a545a6 --- /dev/null +++ b/src/main/java/gregtech/api/graphs/paths/PowerNodePath.java @@ -0,0 +1,111 @@ +package gregtech.api.graphs.paths; + +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.MetaPipeEntity; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; +import net.minecraft.server.MinecraftServer; + +//path for cables +//al calculations like ams and voltage hapens here +public class PowerNodePath extends NodePath { + int mMaxAmps; + int mAmps = 0; + int mLoss; + int mVoltage = 0; + int mMaxVoltage; + int mTick = 0; + boolean mCountUp = true; + + + public PowerNodePath(MetaPipeEntity[] aCables) { + super(aCables); + } + + public int getLoss() { + return mLoss; + } + + public void applyVoltage(int aVoltage, boolean aCountUp) { + int tNewTime = MinecraftServer.getServer().getTickCounter(); + if (mTick != tNewTime) { + reset(tNewTime - mTick); + mTick = tNewTime; + this.mVoltage = aVoltage; + this.mCountUp = aCountUp; + } else if (this.mCountUp != aCountUp && (aVoltage - mLoss)> this.mVoltage || aVoltage > this.mVoltage){ + this.mCountUp = aCountUp; + this.mVoltage = aVoltage; + } + if (aVoltage > mMaxVoltage) { + for (MetaPipeEntity tCable : mPipes) { + if (((GT_MetaPipeEntity_Cable)tCable).mVoltage < this.mVoltage) { + BaseMetaPipeEntity tBaseCable = (BaseMetaPipeEntity) tCable.getBaseMetaTileEntity(); + tBaseCable.setToFire(); + } + } + } + } + + public void addAmps(int aAmps) { + this.mAmps += aAmps; + if (false && this.mAmps > mMaxAmps * 40) { + for (MetaPipeEntity tCable : mPipes) { + if (((GT_MetaPipeEntity_Cable)tCable).mAmperage*40 < this.mAmps) { + BaseMetaPipeEntity tBaseCable = (BaseMetaPipeEntity) tCable.getBaseMetaTileEntity(); + tBaseCable.setToFire(); + } + } + } + } + + //if no amps pass trough for more then 0.5 second reduce them to minimize wrong results + //but still allow the player to see if activity is hapening + public int getAmps() { + int tTime = MinecraftServer.getServer().getTickCounter() - 10; + if (mTick < tTime) { + reset(tTime - mTick); + mTick = tTime; + } + return mAmps; + } + + public int getVoltage(MetaPipeEntity aCable) { + int tLoss = 0; + if (mCountUp) { + for (int i = 0; i < mPipes.length; i++) { + GT_MetaPipeEntity_Cable tCable = (GT_MetaPipeEntity_Cable) mPipes[i]; + tLoss += tCable.mCableLossPerMeter; + if (aCable == tCable) { + return Math.max(mVoltage - tLoss, 0); + } + } + } else { + for (int i = mPipes.length - 1; i >= 0; i--) { + GT_MetaPipeEntity_Cable tCable = (GT_MetaPipeEntity_Cable) mPipes[i]; + tLoss += tCable.mCableLossPerMeter; + if (aCable == tCable) { + return Math.max(mVoltage - tLoss, 0); + } + } + } + return -1; + } + + private void reset(int aTimePassed) { + mAmps = Math.max(0, mAmps - (mMaxAmps * aTimePassed)); + } + + @Override + protected void processPipes() { + super.processPipes(); + mMaxAmps = Integer.MAX_VALUE; + mMaxVoltage = Integer.MAX_VALUE; + for (MetaPipeEntity tCable : mPipes) { + if (tCable instanceof GT_MetaPipeEntity_Cable) { + mMaxAmps = Math.min((int)((GT_MetaPipeEntity_Cable) tCable).mAmperage, mMaxAmps); + mLoss += (int)((GT_MetaPipeEntity_Cable) tCable).mCableLossPerMeter; + mMaxVoltage = Math.min((int)((GT_MetaPipeEntity_Cable) tCable).mVoltage, mMaxVoltage); + } + } + } +} diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java index 158b53068d..24d0576864 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java @@ -61,7 +61,7 @@ public interface IEnergyConnected extends IColoredTileEntity, IHasWorldObjectAnd */ public static final long emitEnergyToNetwork(long aVoltage, long aAmperage, IEnergyConnected aEmitter) { long rUsedAmperes = 0; - for (byte i = 0, j = 0; i < 6 && aAmperage > rUsedAmperes; i++) + for (byte i = 0, j = 0; i < 6 && aAmperage > rUsedAmperes; i++) { if (aEmitter.outputsEnergyTo(i)) { j = GT_Utility.getOppositeSide(i); TileEntity tTileEntity = aEmitter.getTileEntityAtSide(i); @@ -71,6 +71,7 @@ public interface IEnergyConnected extends IColoredTileEntity, IHasWorldObjectAnd if (tColor >= 0 && tColor != aEmitter.getColorization()) continue; } rUsedAmperes += ((IEnergyConnected) tTileEntity).injectEnergyUnits(j, aVoltage, aAmperage - rUsedAmperes); + } else if (tTileEntity instanceof IEnergySink) { if (((IEnergySink) tTileEntity).acceptsEnergyFrom((TileEntity) aEmitter, ForgeDirection.getOrientation(j))) { while (aAmperage > rUsedAmperes && ((IEnergySink) tTileEntity).getDemandedEnergy() > 0 && ((IEnergySink) tTileEntity).injectEnergy(ForgeDirection.getOrientation(j), aVoltage, aVoltage) < aVoltage) @@ -124,6 +125,7 @@ public interface IEnergyConnected extends IColoredTileEntity, IHasWorldObjectAnd } } } + } return rUsedAmperes; } } diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java index 0fd8779244..39cbee3aa9 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java @@ -12,6 +12,8 @@ import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.Textures; import gregtech.api.enums.Textures.BlockIcons; +import gregtech.api.graphs.Node; +import gregtech.api.graphs.paths.NodePath; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IConnectable; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; @@ -62,6 +64,25 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE private int oX = 0, oY = 0, oZ = 0, mTimeStatisticsIndex = 0; private short mID = 0; private long mTickTimer = 0; + protected Node node; + protected NodePath nodePath; + + public Node getNode() { + return node; + } + + public void setNode(Node node) { + this.node = node; + } + + public NodePath getNodePath() { + return nodePath; + } + + public void setNodePath(NodePath nodePath) { + this.nodePath = nodePath; + } + public BaseMetaPipeEntity() { } @@ -262,12 +283,15 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (!hasValidMetaTileEntity()) return; } } + byte oldConections = mConnections; // Mask-out Connection direction bits to keep only Foam related connections mConnections = (byte) (mMetaTileEntity.mConnections | (mConnections & ~IConnectable.CONNECTED_ALL)); // If foam not hardened, tries roll chance to harden if ((mConnections & IConnectable.HAS_FOAM) == IConnectable.HAS_FRESHFOAM && getRandomNumber(1000) == 0) { mConnections = (byte) ((mConnections & ~IConnectable.HAS_FRESHFOAM) | IConnectable.HAS_HARDENEDFOAM); } + if (mTickTimer > 12 && oldConections != mConnections) + GregTech_API.causeCableUpdate(worldObj,xCoord,yCoord,zCoord); } case 8: tCode = 9; diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java index f1a15aca40..3cd66057de 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java @@ -14,6 +14,9 @@ import gregtech.api.GregTech_API; import gregtech.api.enums.ItemList; import gregtech.api.enums.Textures; import gregtech.api.enums.Textures.BlockIcons; +import gregtech.api.graphs.GenerateNodeMap; +import gregtech.api.graphs.GenerateNodeMapPower; +import gregtech.api.graphs.Node; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IEnergyConnected; @@ -40,6 +43,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.Packet; +import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumChatFormatting; @@ -90,6 +94,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE private String mOwnerName = ""; private UUID mOwnerUuid = GT_Utility.defaultUuid; private NBTTagCompound mRecipeStuff = new NBTTagCompound(); + private int cableUpdateDelay = 10; public boolean mWasShutdown = false; @@ -444,6 +449,9 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE mActiveEUOutputs[i] = temp; } } + if (mTickTimer == 22) { + generatePowerNodes(); + } } @@ -568,6 +576,12 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE case 15: tCode++; if (aSideServer) { + if (mTickTimer > 20 && cableUpdateDelay == 0) { + generatePowerNodes(); + cableUpdateDelay--; + } else { + cableUpdateDelay--; + } if (mTickTimer % 10 == 0) { if (mSendClientData) { NW.sendPacketToAllPlayersInRange(worldObj, @@ -869,6 +883,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE mMetaTileEntity.onFacingChange(); doEnetUpdate(); + cableUpdateDelay = 10; if (mMetaTileEntity.shouldTriggerBlockUpdate()) { // If we're triggering a block update this will call onMachineBlockUpdate() @@ -971,6 +986,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public void onMachineBlockUpdate() { if (canAccessData()) mMetaTileEntity.onMachineBlockUpdate(); + cableUpdateDelay = 10; } /** @@ -1098,6 +1114,29 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE return isEnergyOutputSide(aSide); } + public void generatePowerNodes() { + if (isServerSide() && mMetaTileEntity != null && (mMetaTileEntity.isEnetInput() || mMetaTileEntity.isEnetOutput())) { + int time = MinecraftServer.getServer().getTickCounter(); + for (byte i = 0;i<6;i++) { + if (outputsEnergyTo(i,false) || inputEnergyFrom(i,false)) { + IGregTechTileEntity TE = getIGregTechTileEntityAtSide(i); + if (TE instanceof BaseMetaPipeEntity) { + Node node = ((BaseMetaPipeEntity) TE).getNode(); + if (node == null) { + new GenerateNodeMapPower((BaseMetaPipeEntity) TE); + } else if (node.mCreationTime != time) { + GenerateNodeMap.clearNodeMap(node,-1); + new GenerateNodeMapPower((BaseMetaPipeEntity) TE); + } else { +// GenerateNodeMap.clearNodeMap(node,-1); +// new GenerateNodeMapPower((BaseMetaPipeEntity) TE); + } + } + } + } + } + } + @Override public long getOutputAmperage() { if (canAccessData() && mMetaTileEntity.isElectric()) return mMetaTileEntity.maxAmperesOut(); @@ -1399,9 +1438,11 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if(aPlayer.isSneaking() && mMetaTileEntity instanceof GT_MetaTileEntity_BasicMachine && ((GT_MetaTileEntity_BasicMachine)mMetaTileEntity).setMainFacing(GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ))){ GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); + cableUpdateDelay = 10; }else if (mMetaTileEntity.onWrenchRightClick(aSide, GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ), aPlayer, aX, aY, aZ)) { GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); + cableUpdateDelay = 10; } return true; } @@ -1452,6 +1493,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE issueBlockUpdate(); } doEnetUpdate(); + cableUpdateDelay = 10; return true; } @@ -1462,6 +1504,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); } doEnetUpdate(); + cableUpdateDelay = 10; return true; } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 84790ce958..87eee3e6ac 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -63,6 +63,7 @@ public abstract class MetaTileEntity implements IMetaTileEntity { public final ItemStack[] mInventory; public boolean doTickProfilingInThisTick = true; + /** * accessibility to this Field is no longer given, see below */ diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java index 93d947b9d0..90656e03da 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java @@ -9,6 +9,12 @@ import gregtech.api.enums.Dyes; import gregtech.api.enums.Materials; import gregtech.api.enums.TextureSet; import gregtech.api.enums.Textures; +import gregtech.api.graphs.PowerNode; +import gregtech.api.graphs.PowerNodes; +import gregtech.api.graphs.consumers.ConsumerNode; +import gregtech.api.graphs.Node; +import gregtech.api.graphs.NodeList; +import gregtech.api.graphs.paths.PowerNodePath; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.metatileentity.IMetaTileEntityCable; @@ -169,8 +175,28 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile @Override public long transferElectricity(byte aSide, long aVoltage, long aAmperage, HashSet<TileEntity> aAlreadyPassedSet) { - if (!isConnectedAtSide(aSide) && aSide != 6) return 0; - + if (!getBaseMetaTileEntity().isServerSide() || !isConnectedAtSide(aSide) && aSide != 6) return 0; + BaseMetaPipeEntity tBase =(BaseMetaPipeEntity) getBaseMetaTileEntity(); + PowerNode tNode =(PowerNode) tBase.getNode(); + if (tNode != null) { + int tPlace = 0; + Node[] tToPower = new Node[tNode.mConsumers.size()]; + if (tNode.mHadVoltage) { + for (ConsumerNode consumer : tNode.mConsumers) { + if (consumer.needsEnergy()) + tToPower[tPlace++] = consumer; + } + } else { + tNode.mHadVoltage = true; + for (ConsumerNode consumer : tNode.mConsumers) { + tToPower[tPlace++] = consumer; + } + } + return PowerNodes.powerNode(tNode,null,new NodeList(tToPower),(int)aVoltage,(int)aAmperage); + } + if (0< 10) { + return 0; + } long rUsedAmperes = 0; final IGregTechTileEntity baseMetaTile = getBaseMetaTileEntity(); byte i = (byte)((((aSide/2)*2)+2)%6); //this bit of trickery makes sure a direction goes to the next cardinal pair. IE, NS goes to E, EW goes to U, UD goes to N. It's a lame way to make sure locally connected machines on a wire get EU first. @@ -506,15 +532,23 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile @Override public String[] getInfoData() { + BaseMetaPipeEntity base = (BaseMetaPipeEntity) getBaseMetaTileEntity(); + PowerNodePath path =(PowerNodePath) base.getNodePath(); + int amps = 0; + int volts = 0; + if (path != null) { + amps = path.getAmps(); + volts = path.getVoltage(this); + } return new String[]{ //EnumChatFormatting.BLUE + mName + EnumChatFormatting.RESET, "Heat: "+ EnumChatFormatting.RED+ mOverheat +EnumChatFormatting.RESET+" / "+EnumChatFormatting.YELLOW+ mMaxOverheat + EnumChatFormatting.RESET, "Max Load (1t):", - EnumChatFormatting.GREEN + Integer.toString(mTransferredAmperageOK) + EnumChatFormatting.RESET +" A / "+ + EnumChatFormatting.GREEN + Integer.toString(amps) + EnumChatFormatting.RESET +" A / "+ EnumChatFormatting.YELLOW + mAmperage + EnumChatFormatting.RESET +" A", "Max EU/p (1t):", - EnumChatFormatting.GREEN + Long.toString(mTransferredVoltageOK) + EnumChatFormatting.RESET +" EU / "+ + EnumChatFormatting.GREEN + Long.toString(volts) + EnumChatFormatting.RESET +" EU / "+ EnumChatFormatting.YELLOW + mVoltage + EnumChatFormatting.RESET +" EU", "Max Load (20t): "+ EnumChatFormatting.GREEN + mTransferredAmperageLast20OK + EnumChatFormatting.RESET +" A", diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Dynamo.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Dynamo.java index 1156ed7117..b582654cd7 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Dynamo.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Dynamo.java @@ -33,6 +33,11 @@ public class GT_MetaTileEntity_Hatch_Dynamo extends GT_MetaTileEntity_Hatch { } @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPostTick(aBaseMetaTileEntity, aTick); + } + + @Override public boolean isSimpleMachine() { return true; } diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java new file mode 100644 index 0000000000..6bc42e9cc8 --- /dev/null +++ b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java @@ -0,0 +1,71 @@ +package gregtech.api.threads; + +import gregtech.GT_Mod; +import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable; +import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; +import gregtech.common.GT_Proxy; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +public class GT_Runnable_Cable_Update extends GT_Runnable_MachineBlockUpdate { + protected GT_Runnable_Cable_Update(World aWorld, ChunkCoordinates aCoords) { + super(aWorld, aCoords); + } + + public static void setCableUpdateValues(World aWorld, ChunkCoordinates aCoords) { + if (isEnabled) { + EXECUTOR_SERVICE.submit(new GT_Runnable_Cable_Update(aWorld, aCoords)); + } + } + + + @Override + public void run() { + try { + while (!tQueue.isEmpty()) { + final ChunkCoordinates aCoords = tQueue.poll(); + final TileEntity tTileEntity; + final boolean isMachineBlock; + + GT_Proxy.TICK_LOCK.lock(); + try { + //we dont want to go over cables that are in unloaded chuncks + //keeping the lock just to make sure no CME happens + if (world.blockExists(aCoords.posX, aCoords.posY, aCoords.posZ)) { + tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); + } else { + tTileEntity = null; + } + } finally { + GT_Proxy.TICK_LOCK.unlock(); + } + + // See if the block itself needs an update + if (tTileEntity instanceof IMachineBlockUpdateable) + ((IMachineBlockUpdateable) tTileEntity).onMachineBlockUpdate(); + + // Now see if we should add the nearby blocks to the queue: + //only add blocks wich the cable is conected too + if (tTileEntity instanceof BaseMetaPipeEntity && + ((BaseMetaPipeEntity) tTileEntity).getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable) + { + ChunkCoordinates tCoords; + for (byte i = 0;i<6;i++) { + if (((GT_MetaPipeEntity_Cable) ((BaseMetaPipeEntity) tTileEntity).getMetaTileEntity()).isConnectedAtSide(i)) { + ForgeDirection offset = ForgeDirection.getOrientation(i); + if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + offset.offsetX, + aCoords.posY + offset.offsetY, aCoords.posZ + offset.offsetZ))) + tQueue.add(tCoords); + } + } + } + } + } catch (Exception e) { + GT_Mod.GT_FML_LOGGER.error( + "Well this update was broken... " + mCoords + ", mWorld={" + world.getProviderName() + " @dimId " + world.provider.dimensionId + "}", e); + } + } +} diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java index 3ce1daf9b2..cc224b977d 100644 --- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java +++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java @@ -19,10 +19,10 @@ import java.util.concurrent.TimeUnit; public class GT_Runnable_MachineBlockUpdate implements Runnable { // used by runner thread - private final ChunkCoordinates mCoords; - private final World world; - private final Set<ChunkCoordinates> visited = new HashSet<>(80); - private final Queue<ChunkCoordinates> tQueue = new LinkedList<>(); + protected final ChunkCoordinates mCoords; + protected final World world; + protected final Set<ChunkCoordinates> visited = new HashSet<>(80); + protected final Queue<ChunkCoordinates> tQueue = new LinkedList<>(); // Threading private static final ThreadFactory THREAD_FACTORY = r -> { @@ -30,15 +30,14 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { thread.setName("GT_MachineBlockUpdate"); return thread; }; - private static ExecutorService EXECUTOR_SERVICE; + protected static ExecutorService EXECUTOR_SERVICE; // This class should never be initiated outside of this class! - private GT_Runnable_MachineBlockUpdate(World aWorld, ChunkCoordinates aCoords) { + protected GT_Runnable_MachineBlockUpdate(World aWorld, ChunkCoordinates aCoords) { this.world = aWorld; this.mCoords = aCoords; visited.add(aCoords); tQueue.add(aCoords); - } public static boolean isEnabled() { @@ -57,11 +56,10 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable { GT_Runnable_MachineBlockUpdate.isEnabled = isEnabled; } - private static boolean isEnabled = true; + protected static boolean isEnabled = true; public static void setMachineUpdateValues(World aWorld, ChunkCoordinates aCoords) { if (isEnabled) { - aWorld.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ); EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, aCoords)); } } |