return foundPipes;
}
//Visited is checked after, so we can reach the same target twice to allow to keep the shortest path
setVisited.add(new LPPosition(startPipe));
distances.put(new LPPosition(startPipe), startPipe.getDistance());
// first check specialPipeConnections (tesseracts, teleports, other connectors)
List<IPipeInformationProvider> pipez = SimpleServiceLocator.specialpipeconnection.getConnectedPipes(startPipe);
for (IPipeInformationProvider specialpipe : pipez){
if (setVisited.contains(new LPPosition(specialpipe))) {
//Don't go where we have been before
continue;
}
HashMap<CoreRoutedPipe, ExitRoute> result = getConnectedRoutingPipes(specialpipe, connectionFlags, side);
for (Entry<CoreRoutedPipe, ExitRoute> pipe : result.entrySet()) {
pipe.getValue().exitOrientation = ForgeDirection.UNKNOWN;
ExitRoute foundPipe=foundPipes.get(pipe.getKey());
if (foundPipe == null || (pipe.getValue().distanceToDestination < foundPipe.distanceToDestination)) {
// New path OR If new path is better, replace old path
foundPipes.put(pipe.getKey(), pipe.getValue());
}
}
}
ArrayDeque<Pair<TileEntity,ForgeDirection>> connections = new ArrayDeque<Pair<TileEntity,ForgeDirection>>();
//Recurse in all directions
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
if(root && !ForgeDirection.UNKNOWN.equals(side) && !direction.equals(side)) continue;
// tile may be up to 1 second old, but any neighbour pipe change will cause an immidiate update here, so we know that if it has changed, it isn't a pipe that has done so.
TileEntity tile = startPipe.getTile(direction);
if (tile == null) continue;
if(OrientationsUtil.isSide(direction)) {
if (root && tile instanceof ILogisticsPowerProvider) {
if(this.powerNodes==null) {
powerNodes = new ArrayList<Pair<ILogisticsPowerProvider,List<IFilter>>>();
}
//If we are a FireWall pipe add our filter to the pipes
if(startPipe.isFirewallPipe()) {
powerNodes.add(new Pair<ILogisticsPowerProvider,List<IFilter>>((ILogisticsPowerProvider) tile, new OneList<IFilter>(startPipe.getFirewallFilter())));
} else {
powerNodes.add(new Pair<ILogisticsPowerProvider,List<IFilter>>((ILogisticsPowerProvider) tile, Collections.unmodifiableList(new ArrayList<IFilter>(0))));
}
}
if(root && tile instanceof ISubSystemPowerProvider) {
if(this.subPowerProvider==null) {
subPowerProvider = new ArrayList<Pair<ISubSystemPowerProvider,List<IFilter>>>();
}
//If we are a FireWall pipe add our filter to the pipes
if(startPipe.isFirewallPipe()) {
subPowerProvider.add(new Pair<ISubSystemPowerProvider,List<IFilter>>((ISubSystemPowerProvider) tile, new OneList<IFilter>(startPipe.getFirewallFilter())));
} else {
subPowerProvider.add(new Pair<ISubSystemPowerProvider,List<IFilter>>((ISubSystemPowerProvider) tile, Collections.unmodifiableList(new ArrayList<IFilter>(0))));
}
}
}
connections.add(new Pair<TileEntity, ForgeDirection>(tile, direction));
}
while(!connections.isEmpty()) {
Pair<TileEntity,ForgeDirection> pair = connections.pollFirst();
TileEntity tile = pair.getValue1();
ForgeDirection direction = pair.getValue2();
EnumSet<PipeRoutingConnectionType> nextConnectionFlags = EnumSet.copyOf(connectionFlags);
boolean isDirectConnection = false;
int resistance = 0;
if(root) {
List<TileEntity> list = SimpleServiceLocator.specialtileconnection.getConnectedPipes(tile);
if(!list.isEmpty()) {
for(TileEntity pipe:list) {
connections.add(new Pair<TileEntity, ForgeDirection>(pipe, direction));
}
continue;
}
if(!startPipe.getRoutingPipe().getUpgradeManager().hasPowerPassUpgrade()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
}
if(tile instanceof IInventory && startPipe.isRoutingPipe() && startPipe.getRoutingPipe() instanceof IDirectRoutingConnection) {
if(SimpleServiceLocator.connectionManager.hasDirectConnection(startPipe.getRoutingPipe().getRouter())) {
CoreRoutedPipe CRP = SimpleServiceLocator.connectionManager.getConnectedPipe(startPipe.getRoutingPipe().getRouter());
if(CRP != null) {
tile = CRP.container;
isDirectConnection = true;
resistance = ((IDirectRoutingConnection)startPipe.getRoutingPipe()).getConnectionResistance();
}
}
}
if (tile == null) continue;
IPipeInformationProvider currentPipe = SimpleServiceLocator.pipeInformaitonManager.getInformationProviderFor(tile);
if (currentPipe != null && currentPipe.isInitialised() && (isDirectConnection || SimpleServiceLocator.pipeInformaitonManager.canConnect(startPipe, currentPipe, direction, true))) {
//TileGenericPipe currentPipe = (TileGenericPipe) tile;
if (setVisited.contains(new LPPosition(tile))) {
//Don't go where we have been before
continue;
}
if(side != pair.getValue2() && !root) { //Only straight connections for subsystem power
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
if(isDirectConnection) { //ISC doesn't pass power
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerFrom);
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
//Iron, obsidean and liquid pipes will separate networks
if(currentPipe.divideNetwork()) {
continue;
}
if(currentPipe.powerOnly()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canRouteTo);
nextConnectionFlags.remove(PipeRoutingConnectionType.canRequestFrom);
}
if(startPipe.isOnewayPipe()) {
if(!startPipe.isOutputOpen(direction)) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canRouteTo);
}
}
if(currentPipe.isOnewayPipe()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
if(!currentPipe.isOutputOpen(direction.getOpposite())) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canRequestFrom);
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerFrom);
}
}
if(nextConnectionFlags.isEmpty()) { //don't bother going somewhere we can't do anything with
continue;
}
int beforeRecurseCount = foundPipes.size();
HashMap<CoreRoutedPipe, ExitRoute> result = getConnectedRoutingPipes(currentPipe, nextConnectionFlags, direction);
for(Entry<CoreRoutedPipe, ExitRoute> pipeEntry : result.entrySet()) {
//Update Result with the direction we took
pipeEntry.getValue().exitOrientation = direction;
ExitRoute foundPipe = foundPipes.get(pipeEntry.getKey());
if (foundPipe==null) {
// New path
foundPipes.put(pipeEntry.getKey(), pipeEntry.getValue());
//Add resistance
pipeEntry.getValue().distanceToDestination += resistance;
}
else if (pipeEntry.getValue().distanceToDestination + resistance < foundPipe.distanceToDestination) {
//If new path is better, replace old path, otherwise do nothing
foundPipes.put(pipeEntry.getKey(), pipeEntry.getValue());
//Add resistance
pipeEntry.getValue().distanceToDestination += resistance;
}
}
if (foundPipes.size() > beforeRecurseCount && pathPainter != null) {
pathPainter.addLaser(startPipe.getWorld(), new LaserData(startPipe.getX(), startPipe.getY(), startPipe.getZ(), direction, connectionFlags));
}
}
}
setVisited.remove(new LPPosition(startPipe));
distances.remove(new LPPosition(startPipe));
if(startPipe.isRoutingPipe()) { // ie, has the recursion returned to the pipe it started from?
for(ExitRoute e:foundPipes.values()) {
e.root = (startPipe.getRoutingPipe()).getRouter();
}
}