Skip to content

Commit 7a9b1db

Browse files
authored
Electric pipes rework (GregTechCEu#78)
1 parent 757264a commit 7a9b1db

11 files changed

+394
-296
lines changed

src/main/java/gregtech/api/capability/IEnergyContainer.java

+28-6
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,32 @@
55
public interface IEnergyContainer {
66

77
/**
8+
* This method is basically {@link #changeEnergy(long)}, but it also handles amperes.
9+
* This method should always be used when energy is passed between blocks.
10+
*
11+
* @param voltage amount of energy packets (energy to add / input voltage)
12+
* @param amperage packet size (energy to add / input amperage)
813
* @return amount of used amperes. 0 if not accepted anything.
914
*/
1015
long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage);
1116

17+
/**
18+
* @return if this container accepts energy from the given side
19+
*/
1220
boolean inputsEnergy(EnumFacing side);
1321

22+
/**
23+
* @return if this container can output energy to the given side
24+
*/
1425
default boolean outputsEnergy(EnumFacing side) {
1526
return false;
1627
}
1728

1829
/**
30+
* This changes the amount stored.
31+
* <b>This should only be used internally</b> (f.e. draining while working or filling while generating).
32+
* For transfer between blocks use {@link #acceptEnergyFromNetwork(EnumFacing, long, long)}!!!
33+
*
1934
* @param differenceAmount amount of energy to add (>0) or remove (<0)
2035
* @return amount of energy added or removed
2136
*/
@@ -41,45 +56,52 @@ default long removeEnergy(long energyToRemove) {
4156
return changeEnergy(-energyToRemove);
4257
}
4358

59+
/**
60+
* @return the maximum amount of energy that can be inserted
61+
*/
4462
default long getEnergyCanBeInserted() {
4563
return getEnergyCapacity() - getEnergyStored();
4664
}
4765

4866
/**
49-
* Gets the stored electric energy
67+
* @return amount of currently stored energy
5068
*/
5169
long getEnergyStored();
5270

5371
/**
54-
* Gets the largest electric energy capacity
72+
* @return maximum amount of storable energy
5573
*/
5674
long getEnergyCapacity();
5775

5876
/**
59-
* Gets the amount of energy packets per tick.
77+
* @return maximum amount of outputable energy packets per tick
6078
*/
6179
default long getOutputAmperage() {
6280
return 0L;
6381
}
6482

6583
/**
66-
* Gets the output in energy units per energy packet.
84+
* @return output energy packet size
6785
*/
6886
default long getOutputVoltage() {
6987
return 0L;
7088
}
7189

7290
/**
73-
* Gets the amount of energy packets this machine can receive
91+
* @return maximum amount of receivable energy packets per tick
7492
*/
7593
long getInputAmperage();
7694

7795
/**
78-
* Gets the maximum voltage this machine can receive in one energy packet.
96+
* @return output energy packet size
7997
* Overflowing this value will explode machine.
8098
*/
8199
long getInputVoltage();
82100

101+
/**
102+
* @return true if information like energy capacity should be hidden from TOP.
103+
* Useful for cables
104+
*/
83105
default boolean isOneProbeHidden() {
84106
return false;
85107
}

src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class EnergyContainerBatteryBuffer extends MTETrait implements IEnergyCon
2323

2424
private final BitSet batterySlotsUsedThisTick = new BitSet();
2525
private final int tier;
26+
private long amps = 0;
2627

2728
public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier) {
2829
super(metaTileEntity);
@@ -31,11 +32,14 @@ public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier) {
3132

3233
@Override
3334
public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) {
34-
long initialAmperage = amperage;
35+
long usedAmps = 0;
36+
amperage -= amps;
37+
if(amperage <= 0)
38+
return 0;
3539
if (side == null || inputsEnergy(side)) {
3640
if (voltage > getInputVoltage()) {
3741
GTUtility.doOvervoltageExplosion(metaTileEntity, voltage);
38-
return Math.min(amperage, getInputAmperage());
42+
return Math.min(amperage, getInputAmperage() - amps);
3943
}
4044
IItemHandlerModifiable inventory = getInventory();
4145
for (int i = 0; i < inventory.getSlots(); i++) {
@@ -47,15 +51,15 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage
4751
chargeItemWithVoltage(electricItem, voltage, getTier(), false);
4852
inventory.setStackInSlot(i, batteryStack);
4953
this.batterySlotsUsedThisTick.set(i);
50-
if (--amperage == 0) break;
54+
if(++usedAmps == amperage) break;
5155
}
5256
}
5357
}
54-
long amperageUsed = initialAmperage - amperage;
55-
if (amperageUsed > 0L) {
58+
if (usedAmps > 0L) {
5659
notifyEnergyListener(false);
5760
}
58-
return amperageUsed;
61+
amps += usedAmps;
62+
return usedAmps;
5963
}
6064

6165
private static boolean chargeItemWithVoltage(IElectricItem electricItem, long voltage, int tier, boolean simulate) {
@@ -73,6 +77,7 @@ private static long chargeItem(IElectricItem electricItem, long amount, int tier
7377

7478
@Override
7579
public void update() {
80+
amps = 0;
7681
if (!metaTileEntity.getWorld().isRemote) {
7782
this.batterySlotsUsedThisTick.clear();
7883
EnumFacing outFacing = metaTileEntity.getFrontFacing();

src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public class EnergyContainerHandler extends MTETrait implements IEnergyContainer
2929
private Predicate<EnumFacing> sideInputCondition;
3030
private Predicate<EnumFacing> sideOutputCondition;
3131

32+
private long amps = 0;
33+
3234
public EnergyContainerHandler(MetaTileEntity tileEntity, long maxCapacity, long maxInputVoltage, long maxInputAmperage, long maxOutputVoltage, long maxOutputAmperage) {
3335
super(tileEntity);
3436
this.maxCapacity = maxCapacity;
@@ -133,6 +135,7 @@ public boolean dischargeOrRechargeEnergyContainers(IItemHandlerModifiable itemHa
133135

134136
@Override
135137
public void update() {
138+
amps = 0;
136139
if (getMetaTileEntity().getWorld().isRemote)
137140
return;
138141
if (getEnergyStored() >= getOutputVoltage() && getOutputVoltage() > 0 && getOutputAmperage() > 0) {
@@ -159,16 +162,18 @@ public void update() {
159162

160163
@Override
161164
public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) {
165+
if(amps >= getInputAmperage()) return 0;
162166
long canAccept = getEnergyCapacity() - getEnergyStored();
163-
if (voltage > 0L && amperage > 0L && (side == null || inputsEnergy(side))) {
167+
if (voltage > 0L && (side == null || inputsEnergy(side))) {
164168
if (voltage > getInputVoltage()) {
165169
GTUtility.doOvervoltageExplosion(metaTileEntity, voltage);
166-
return Math.min(amperage, getInputAmperage());
170+
return Math.min(amperage, getInputAmperage() - amps);
167171
}
168172
if (canAccept >= voltage) {
169-
long amperesAccepted = Math.min(canAccept / voltage, Math.min(amperage, getInputAmperage()));
173+
long amperesAccepted = Math.min(canAccept / voltage, Math.min(amperage, getInputAmperage() - amps));
170174
if (amperesAccepted > 0) {
171175
setEnergyStored(getEnergyStored() + voltage * amperesAccepted);
176+
amps += amperesAccepted;
172177
return amperesAccepted;
173178
}
174179
}

src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java

+18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import codechicken.lib.render.pipeline.IVertexOperation;
55
import codechicken.lib.vec.Matrix4;
66
import gregtech.api.GTValues;
7+
import gregtech.api.capability.impl.EnergyContainerHandler;
78
import gregtech.api.capability.impl.FilteredFluidHandler;
89
import gregtech.api.capability.impl.FluidTankList;
910
import gregtech.api.capability.impl.RecipeLogicEnergy;
@@ -42,6 +43,23 @@ protected RecipeLogicEnergy createWorkable(RecipeMap<?> recipeMap) {
4243
return new RecipeLogicEnergy(this, recipeMap, () -> energyContainer);
4344
}
4445

46+
@Override
47+
protected void reinitializeEnergyContainer() {
48+
long tierVoltage = GTValues.V[getTier()];
49+
if (isEnergyEmitter()) {
50+
this.energyContainer = EnergyContainerHandler.emitterContainer(this,
51+
tierVoltage * 64L, tierVoltage, getMaxInputOutputAmperage());
52+
} else this.energyContainer = new EnergyContainerHandler(this, tierVoltage * 64L, tierVoltage, 2, 0L, 0L) {
53+
@Override
54+
public long getInputAmperage() {
55+
if(getEnergyCapacity() / 2 > getEnergyStored() && workable.isActive()) {
56+
return 2;
57+
}
58+
return 1;
59+
}
60+
};
61+
}
62+
4563
@Override
4664
protected long getMaxInputOutputAmperage() {
4765
return 2L;

src/main/java/gregtech/common/pipelike/cable/BlockCable.java

+18-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
import gregtech.api.unification.material.MaterialRegistry;
1414
import gregtech.api.unification.material.properties.WireProperties;
1515
import gregtech.api.util.GTUtility;
16-
import gregtech.common.ConfigHolder;
1716
import gregtech.common.pipelike.cable.net.EnergyNet;
1817
import gregtech.common.pipelike.cable.net.WorldENet;
1918
import gregtech.common.pipelike.cable.tile.TileEntityCable;
2019
import gregtech.common.pipelike.cable.tile.TileEntityCableTickable;
20+
import gregtech.common.pipelike.fluidpipe.net.FluidPipeNet;
2121
import gregtech.common.render.CableRenderer;
2222
import gregtech.common.tools.DamageValues;
23+
import net.minecraft.block.Block;
2324
import net.minecraft.block.ITileEntityProvider;
2425
import net.minecraft.block.state.IBlockState;
2526
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -111,6 +112,17 @@ public int onPipeToolUsed(ItemStack stack, EnumFacing coverSide, IPipeTile<Insul
111112
return -1;
112113
}
113114

115+
@Override
116+
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {
117+
super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
118+
if (!worldIn.isRemote) {
119+
EnergyNet enet = getWorldPipeNet(worldIn).getNetFromPos(pos);
120+
if (enet != null) {
121+
enet.nodeNeighbourChanged(pos);
122+
}
123+
}
124+
}
125+
114126
@Override
115127
public boolean canPipesConnect(IPipeTile<Insulation, WireProperties> selfTile, EnumFacing side, IPipeTile<Insulation, WireProperties> sideTile) {
116128
return selfTile instanceof TileEntityCable && sideTile instanceof TileEntityCable;
@@ -125,12 +137,12 @@ public boolean canPipeConnectToBlock(IPipeTile<Insulation, WireProperties> selfT
125137
public void onEntityCollision(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Entity entityIn) {
126138
if (worldIn.isRemote) return;
127139
Insulation insulation = getPipeTileEntity(worldIn, pos).getPipeType();
128-
if (!worldIn.isRemote && insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) {
140+
if (insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) {
129141
EntityLivingBase entityLiving = (EntityLivingBase) entityIn;
130-
EnergyNet energyNet = getWorldPipeNet(worldIn).getNetFromPos(pos);
131-
if (energyNet != null && (energyNet.getAllNodes().get(pos).data.lossPerBlock > 0)) {
132-
long voltage = energyNet.getLastMaxVoltage();
133-
long amperage = energyNet.getLastAmperage();
142+
TileEntityCable cable = (TileEntityCable) getPipeTileEntity(worldIn, pos);
143+
if (cable != null && cable.getNodeData().lossPerBlock > 0) {
144+
long voltage = cable.getCurrentVoltage();
145+
long amperage = cable.getCurrentAmperage();
134146
if (voltage > 0L && amperage > 0L) {
135147
float damageAmount = (GTUtility.getTierByVoltage(voltage) + 1) * amperage * 4;
136148
entityLiving.attackEntityFrom(DamageSources.getElectricDamage(), damageAmount);

src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java

+23-56
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,50 @@
44
import gregtech.api.pipenet.PipeNet;
55
import gregtech.api.pipenet.WorldPipeNet;
66
import gregtech.api.unification.material.properties.WireProperties;
7-
import gregtech.api.util.PerTickLongCounter;
87
import net.minecraft.nbt.NBTTagCompound;
98
import net.minecraft.util.EnumFacing;
109
import net.minecraft.util.math.BlockPos;
11-
import net.minecraft.util.math.BlockPos.MutableBlockPos;
1210

13-
import java.util.ArrayList;
14-
import java.util.HashSet;
11+
import java.util.Comparator;
12+
import java.util.HashMap;
1513
import java.util.List;
16-
import java.util.Stack;
14+
import java.util.Map;
1715

1816
public class EnergyNet extends PipeNet<WireProperties> {
1917

20-
private final PerTickLongCounter currentAmperageCounter = new PerTickLongCounter(0L);
21-
private final PerTickLongCounter currentMaxVoltageCounter = new PerTickLongCounter(0L);
18+
private final Map<BlockPos, List<RoutePath>> NET_DATA = new HashMap<>();
2219

2320
protected EnergyNet(WorldPipeNet<WireProperties, EnergyNet> world) {
2421
super(world);
2522
}
2623

27-
public long getLastAmperage() {
28-
return currentAmperageCounter.getLast(worldData.getWorld());
24+
public List<RoutePath> getNetData(BlockPos pipePos) {
25+
List<RoutePath> data = NET_DATA.get(pipePos);
26+
if (data == null) {
27+
data = EnergyNetWalker.createNetData(this, getWorldData(), pipePos);
28+
data.sort(Comparator.comparingInt(RoutePath::getDistance));
29+
NET_DATA.put(pipePos, data);
30+
}
31+
return data;
2932
}
3033

31-
public long getLastMaxVoltage() {
32-
return currentMaxVoltageCounter.getLast(worldData.getWorld());
34+
public void nodeNeighbourChanged(BlockPos pos) {
35+
NET_DATA.clear();
3336
}
3437

35-
public void incrementCurrentAmperage(long amperage, long voltage) {
36-
currentAmperageCounter.increment(worldData.getWorld(), amperage);
37-
long currentMaxVoltage = currentMaxVoltageCounter.get(worldData.getWorld());
38-
if (voltage > currentMaxVoltage) {
39-
currentMaxVoltageCounter.set(worldData.getWorld(), voltage);
40-
}
38+
@Override
39+
protected void updateBlockedConnections(BlockPos nodePos, EnumFacing facing, boolean isBlocked) {
40+
super.updateBlockedConnections(nodePos, facing, isBlocked);
41+
NET_DATA.clear();
4142
}
4243

43-
public List<RoutePath> computePatches(BlockPos startPos) {
44-
ArrayList<RoutePath> readyPaths = new ArrayList<>();
45-
RoutePath currentPath = new RoutePath();
46-
Node<WireProperties> firstNode = getNodeAt(startPos);
47-
currentPath.path.put(startPos, firstNode.data);
48-
readyPaths.add(currentPath.cloneAndCompute(startPos));
49-
HashSet<BlockPos> observedSet = new HashSet<>();
50-
observedSet.add(startPos);
51-
MutableBlockPos currentPos = new MutableBlockPos(startPos);
52-
Stack<EnumFacing> moveStack = new Stack<>();
53-
main:
54-
while (true) {
55-
for (EnumFacing facing : EnumFacing.VALUES) {
56-
currentPos.move(facing);
57-
Node<WireProperties> secondNode = getNodeAt(currentPos);
58-
if (secondNode != null && canNodesConnect(firstNode, facing, secondNode, this) && !observedSet.contains(currentPos)) {
59-
BlockPos immutablePos = currentPos.toImmutable();
60-
observedSet.add(immutablePos);
61-
firstNode = secondNode;
62-
moveStack.push(facing.getOpposite());
63-
currentPath.path.put(immutablePos, getNodeAt(immutablePos).data);
64-
if (secondNode.isActive) {
65-
//if we are on active node, this is end of our path
66-
RoutePath finalizedPath = currentPath.cloneAndCompute(immutablePos);
67-
readyPaths.add(finalizedPath);
68-
}
69-
continue main;
70-
} else {
71-
currentPos.move(facing.getOpposite());
72-
}
73-
}
74-
if (!moveStack.isEmpty()) {
75-
currentPos.move(moveStack.pop());
76-
//also remove already visited block from path
77-
currentPath.path.remove(currentPos);
78-
} else break;
79-
}
80-
return readyPaths;
44+
@Override
45+
protected void transferNodeData(Map<BlockPos, Node<WireProperties>> transferredNodes, PipeNet<WireProperties> parentNet) {
46+
super.transferNodeData(transferredNodes, parentNet);
47+
NET_DATA.clear();
48+
((EnergyNet) parentNet).NET_DATA.clear();
8149
}
8250

83-
8451
@Override
8552
protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) {
8653
tagCompound.setInteger("voltage", nodeData.voltage);

0 commit comments

Comments
 (0)