Fix the EnergyNetwork memory leak.
This commit is contained in:
parent
c2c031ef2a
commit
18519b5fa6
4 changed files with 185 additions and 26 deletions
|
@ -23,13 +23,15 @@ import buildcraft.api.power.IPowerReceptor;
|
|||
|
||||
public class EnergyNetwork
|
||||
{
|
||||
public Set<IUniversalCable> cables = new HashSet<IUniversalCable>();
|
||||
public HashSet<IUniversalCable> cables = new HashSet<IUniversalCable>();
|
||||
|
||||
public Set<TileEntity> possibleAcceptors = new HashSet<TileEntity>();
|
||||
public Map<TileEntity, ForgeDirection> acceptorDirections = new HashMap<TileEntity, ForgeDirection>();
|
||||
|
||||
private double joulesTransmitted = 0;
|
||||
private double joulesLastTick = 0;
|
||||
private int ticksSinceCreate = 0;
|
||||
private boolean fixed = false;
|
||||
|
||||
public EnergyNetwork(IUniversalCable... varCables)
|
||||
{
|
||||
|
@ -37,6 +39,20 @@ public class EnergyNetwork
|
|||
EnergyNetworkRegistry.getInstance().registerNetwork(this);
|
||||
}
|
||||
|
||||
public EnergyNetwork(Set<EnergyNetwork> networks)
|
||||
{
|
||||
for (EnergyNetwork net : networks)
|
||||
{
|
||||
if(net != null)
|
||||
{
|
||||
addAllCables(net.cables);
|
||||
net.deregister();
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
EnergyNetworkRegistry.getInstance().registerNetwork(this);
|
||||
}
|
||||
|
||||
public double getEnergyNeeded(ArrayList<TileEntity> ignored)
|
||||
{
|
||||
double totalNeeded = 0;
|
||||
|
@ -155,7 +171,8 @@ public class EnergyNetwork
|
|||
|
||||
public void refresh()
|
||||
{
|
||||
Iterator it = cables.iterator();
|
||||
Set<IUniversalCable> iterCables = (Set<IUniversalCable>) cables.clone();
|
||||
Iterator<IUniversalCable> it = iterCables.iterator();
|
||||
|
||||
possibleAcceptors.clear();
|
||||
acceptorDirections.clear();
|
||||
|
@ -164,20 +181,17 @@ public class EnergyNetwork
|
|||
{
|
||||
IUniversalCable conductor = (IUniversalCable)it.next();
|
||||
|
||||
if(conductor == null)
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
else if(((TileEntity)conductor).isInvalid())
|
||||
if(conductor == null || ((TileEntity)conductor).isInvalid())
|
||||
{
|
||||
it.remove();
|
||||
cables.remove(conductor);
|
||||
}
|
||||
else {
|
||||
conductor.setNetwork(this);
|
||||
}
|
||||
}
|
||||
|
||||
for(IUniversalCable cable : cables)
|
||||
for(IUniversalCable cable : iterCables)
|
||||
{
|
||||
TileEntity[] acceptors = CableUtils.getConnectedEnergyAcceptors((TileEntity)cable);
|
||||
|
||||
|
@ -194,24 +208,26 @@ public class EnergyNetwork
|
|||
|
||||
public void merge(EnergyNetwork network)
|
||||
{
|
||||
EnergyNetworkRegistry registry = EnergyNetworkRegistry.getInstance();
|
||||
|
||||
if(network != null && network != this)
|
||||
{
|
||||
EnergyNetwork newNetwork = new EnergyNetwork();
|
||||
newNetwork.cables.addAll(cables);
|
||||
registry.removeNetwork(this);
|
||||
newNetwork.cables.addAll(network.cables);
|
||||
registry.removeNetwork(network);
|
||||
Set<EnergyNetwork> networks = new HashSet();
|
||||
networks.add(this);
|
||||
networks.add(network);
|
||||
EnergyNetwork newNetwork = new EnergyNetwork(networks);
|
||||
newNetwork.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAllCables(Set<IUniversalCable> newCables)
|
||||
{
|
||||
cables.addAll(newCables);
|
||||
}
|
||||
|
||||
public void split(IUniversalCable splitPoint)
|
||||
{
|
||||
if(splitPoint instanceof TileEntity)
|
||||
{
|
||||
cables.remove(splitPoint);
|
||||
removeCable(splitPoint);
|
||||
|
||||
TileEntity[] connectedBlocks = new TileEntity[6];
|
||||
boolean[] dealtWith = {false, false, false, false, false, false};
|
||||
|
@ -233,7 +249,7 @@ public class EnergyNetwork
|
|||
if(connectedBlockA instanceof IUniversalCable && !dealtWith[countOne])
|
||||
{
|
||||
NetworkFinder finder = new NetworkFinder(((TileEntity)splitPoint).worldObj, Object3D.get(connectedBlockA), Object3D.get((TileEntity)splitPoint));
|
||||
List<Object3D> partNetwork = finder.findNetwork();
|
||||
List<Object3D> partNetwork = finder.exploreNetwork();
|
||||
|
||||
for(int countTwo = countOne + 1; countTwo < connectedBlocks.length; countTwo++)
|
||||
{
|
||||
|
@ -267,10 +283,50 @@ public class EnergyNetwork
|
|||
}
|
||||
}
|
||||
|
||||
EnergyNetworkRegistry.getInstance().removeNetwork(this);
|
||||
deregister();
|
||||
}
|
||||
}
|
||||
|
||||
public void fixMessedUpNetwork(IUniversalCable cable)
|
||||
{
|
||||
System.out.println("Fixing Network");
|
||||
if(cable instanceof TileEntity)
|
||||
{
|
||||
NetworkFinder finder = new NetworkFinder(((TileEntity) cable).getWorldObj(), Object3D.get((TileEntity)cable), null);
|
||||
List<Object3D> partNetwork = finder.exploreNetwork();
|
||||
Set<IUniversalCable> newCables = new HashSet<IUniversalCable>();
|
||||
for(Object3D node : partNetwork)
|
||||
{
|
||||
TileEntity nodeTile = node.getTileEntity(((TileEntity)cable).worldObj);
|
||||
|
||||
if(nodeTile instanceof IUniversalCable)
|
||||
{
|
||||
((IUniversalCable) nodeTile).removeFromNetwork();
|
||||
newCables.add((IUniversalCable)nodeTile);
|
||||
}
|
||||
}
|
||||
EnergyNetwork newNetwork = new EnergyNetwork(newCables.toArray(new IUniversalCable[0]));
|
||||
newNetwork.refresh();
|
||||
newNetwork.fixed = true;
|
||||
deregister();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeCable(IUniversalCable cable)
|
||||
{
|
||||
cables.remove(cable);
|
||||
if(cables.size() == 0)
|
||||
{
|
||||
deregister();
|
||||
}
|
||||
}
|
||||
|
||||
public void deregister()
|
||||
{
|
||||
cables.clear();
|
||||
EnergyNetworkRegistry.getInstance().removeNetwork(this);
|
||||
}
|
||||
|
||||
public static class NetworkFinder
|
||||
{
|
||||
public World worldObj;
|
||||
|
@ -313,7 +369,7 @@ public class EnergyNetwork
|
|||
}
|
||||
}
|
||||
|
||||
public List<Object3D> findNetwork()
|
||||
public List<Object3D> exploreNetwork()
|
||||
{
|
||||
loopAll(start);
|
||||
|
||||
|
@ -350,6 +406,22 @@ public class EnergyNetwork
|
|||
return "[EnergyNetwork] " + cables.size() + " cables, " + possibleAcceptors.size() + " acceptors.";
|
||||
}
|
||||
|
||||
|
||||
public void tick()
|
||||
{
|
||||
clearJoulesTransmitted();
|
||||
//Fix weird behaviour periodically.
|
||||
if(!fixed)
|
||||
{
|
||||
++ticksSinceCreate;
|
||||
if(ticksSinceCreate > 1200)
|
||||
{
|
||||
ticksSinceCreate = 0;
|
||||
fixMessedUpNetwork(cables.toArray(new IUniversalCable[0])[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearJoulesTransmitted()
|
||||
{
|
||||
joulesLastTick = joulesTransmitted;
|
||||
|
|
|
@ -13,7 +13,7 @@ public class EnergyNetworkRegistry implements ITickHandler
|
|||
{
|
||||
private static EnergyNetworkRegistry INSTANCE = new EnergyNetworkRegistry();
|
||||
|
||||
private Set<EnergyNetwork> networks = new HashSet<EnergyNetwork>();
|
||||
private HashSet<EnergyNetwork> networks = new HashSet<EnergyNetwork>();
|
||||
|
||||
public EnergyNetworkRegistry()
|
||||
{
|
||||
|
@ -38,6 +38,17 @@ public class EnergyNetworkRegistry implements ITickHandler
|
|||
}
|
||||
}
|
||||
|
||||
public void pruneEmptyNetworks() {
|
||||
for(EnergyNetwork e : networks)
|
||||
{
|
||||
if(e.cables.size() == 0)
|
||||
{
|
||||
removeNetwork(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
|
@ -47,9 +58,13 @@ public class EnergyNetworkRegistry implements ITickHandler
|
|||
@Override
|
||||
public void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
for(EnergyNetwork net : networks)
|
||||
Set<EnergyNetwork> iterNetworks = (Set<EnergyNetwork>) networks.clone();
|
||||
for(EnergyNetwork net : iterNetworks)
|
||||
{
|
||||
net.clearJoulesTransmitted();
|
||||
if(networks.contains(net))
|
||||
{
|
||||
net.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,20 @@ public interface IUniversalCable
|
|||
{
|
||||
/**
|
||||
* Gets the EnergyNetwork currently in use by this cable segment.
|
||||
* Will try to connect to adjacent networks or create a new one
|
||||
* @return EnergyNetwork this cable is using
|
||||
*/
|
||||
public EnergyNetwork getNetwork();
|
||||
|
||||
/**
|
||||
* Gets the EnergyNetwork currently in use by this cable segment.
|
||||
* @param createIfNull - If true, the cable will try and connect to an
|
||||
* adjacent network, merging several if necessary, or creating a new one
|
||||
* if none is available
|
||||
* @return EnergyNetwork this cable is using
|
||||
*/
|
||||
public EnergyNetwork getNetwork(boolean createIfNull);
|
||||
|
||||
/**
|
||||
* Sets this cable segment's EnergyNetwork to a new value.
|
||||
* @param network - EnergyNetwork to set to
|
||||
|
@ -23,4 +33,16 @@ public interface IUniversalCable
|
|||
* Refreshes the cable's EnergyNetwork.
|
||||
*/
|
||||
public void refreshNetwork();
|
||||
|
||||
/**
|
||||
* Remove a cable from its network.
|
||||
*/
|
||||
public void removeFromNetwork();
|
||||
|
||||
/**
|
||||
* Call this if you're worried a cable's network is messed up and you want
|
||||
* it to try and fix itself.
|
||||
*/
|
||||
public void fixNetwork();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mekanism.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import mekanism.api.Object3D;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -35,14 +36,47 @@ public class TileEntityUniversalCable extends TileEntity implements IUniversalCa
|
|||
@Override
|
||||
public EnergyNetwork getNetwork()
|
||||
{
|
||||
if(energyNetwork == null)
|
||||
return getNetwork(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnergyNetwork getNetwork(boolean createIfNull)
|
||||
{
|
||||
if(energyNetwork == null && createIfNull)
|
||||
{
|
||||
energyNetwork = new EnergyNetwork(this);
|
||||
TileEntity[] adjacentCables = CableUtils.getConnectedCables(this);
|
||||
HashSet<EnergyNetwork> connectedNets = new HashSet<EnergyNetwork>();
|
||||
for(TileEntity cable : adjacentCables)
|
||||
{
|
||||
if(cable instanceof IUniversalCable && ((IUniversalCable)cable).getNetwork(false) != null)
|
||||
{
|
||||
connectedNets.add(((IUniversalCable)cable).getNetwork());
|
||||
}
|
||||
}
|
||||
if(connectedNets.size() == 0)
|
||||
{
|
||||
energyNetwork = new EnergyNetwork(this);
|
||||
}
|
||||
else if(connectedNets.size() == 1)
|
||||
{
|
||||
energyNetwork = (EnergyNetwork)connectedNets.toArray()[0];
|
||||
energyNetwork.cables.add(this);
|
||||
}
|
||||
else {
|
||||
energyNetwork = new EnergyNetwork(connectedNets);
|
||||
energyNetwork.cables.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
return energyNetwork;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixNetwork()
|
||||
{
|
||||
getNetwork().fixMessedUpNetwork(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate()
|
||||
{
|
||||
|
@ -57,7 +91,17 @@ public class TileEntityUniversalCable extends TileEntity implements IUniversalCa
|
|||
@Override
|
||||
public void setNetwork(EnergyNetwork network)
|
||||
{
|
||||
energyNetwork = network;
|
||||
if(network != energyNetwork)
|
||||
{
|
||||
removeFromNetwork();
|
||||
energyNetwork = network;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFromNetwork()
|
||||
{
|
||||
energyNetwork.removeCable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -105,6 +149,12 @@ public class TileEntityUniversalCable extends TileEntity implements IUniversalCa
|
|||
{
|
||||
return INFINITE_EXTENT_AABB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload() {
|
||||
invalidate();
|
||||
EnergyNetworkRegistry.getInstance().pruneEmptyNetworks();
|
||||
}
|
||||
}
|
||||
|
||||
class CablePowerProvider extends PowerProvider
|
||||
|
|
Loading…
Reference in a new issue