use of logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation in project LogisticsPipes by RS485.
the class LPRobotConnectionControl method getConnections.
@Override
public List<ConnectionInformation> getConnections(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connection, ForgeDirection side) {
List<ConnectionInformation> list = new ArrayList<>();
LogisticsTileGenericPipe pipe = (LogisticsTileGenericPipe) startPipe;
if (pipe == null || pipe.tilePart.getOriginal() == null) {
// Proxy got disabled
return list;
}
DoubleCoordinates pos = new DoubleCoordinates(startPipe);
pos.center();
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
PipePluggable pluggable = ((TileGenericPipe) pipe.tilePart.getOriginal()).getPipePluggable(dir);
if (!(pluggable instanceof RobotStationPluggable)) {
continue;
}
DockingStation station = ((RobotStationPluggable) pluggable).getStation();
if (!station.isTaken()) {
continue;
}
EntityRobotBase robot = station.robotTaking();
if (robot == null) {
continue;
}
if (!(robot.getBoard() instanceof LogisticsRoutingBoardRobot)) {
continue;
}
if (robot.isDead) {
continue;
}
if (!((LogisticsRoutingBoardRobot) robot.getBoard()).isAcceptsItems()) {
continue;
}
DoubleCoordinates robotPos = new DoubleCoordinates(robot);
if (((LogisticsRoutingBoardRobot) robot.getBoard()).getCurrentTarget() != null) {
Pair<Double, LogisticsRoutingBoardRobot> currentTarget = ((LogisticsRoutingBoardRobot) robot.getBoard()).getCurrentTarget();
DoubleCoordinates pipePos = currentTarget.getValue2().getLinkedStationPosition();
TileEntity connectedPipeTile = pipePos.getTileEntity(pipe.getWorldObj());
if (!(connectedPipeTile instanceof LogisticsTileGenericPipe)) {
continue;
}
LogisticsTileGenericPipe connectedPipe = (LogisticsTileGenericPipe) connectedPipeTile;
if (!connectedPipe.isRoutingPipe()) {
continue;
}
IPipeInformationProvider connectedInfo = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(connectedPipe);
EntityRobotBase connectedRobot = currentTarget.getValue2().robot;
if (connectedRobot == null) {
continue;
}
if (!(connectedRobot.getBoard() instanceof LogisticsRoutingBoardRobot)) {
continue;
}
if (connectedRobot.isDead) {
continue;
}
if (connectedRobot.getZoneToWork() != null && !connectedRobot.getZoneToWork().contains(robotPos.getXCoord(), robotPos.getYCoord(), robotPos.getZCoord())) {
continue;
}
if (!((LogisticsRoutingBoardRobot) connectedRobot.getBoard()).isAcceptsItems()) {
continue;
}
DoubleCoordinates connectedRobotPos = new DoubleCoordinates(connectedRobot);
if (CoordinateUtils.add(new DoubleCoordinates(pipePos).center(), currentTarget.getValue2().robot.getLinkedStation().side(), 0.5).distanceTo(connectedRobotPos) > 0.05) {
// Not at station
continue;
}
EnumSet<PipeRoutingConnectionType> newCon = connection.clone();
newCon.removeAll(EnumSet.of(PipeRoutingConnectionType.canPowerFrom, PipeRoutingConnectionType.canPowerSubSystemFrom));
double distance = CoordinateUtils.add(new DoubleCoordinates(currentTarget.getValue2().getLinkedStationPosition()).center(), currentTarget.getValue2().robot.getLinkedStation().side(), 0.5).distanceTo(robotPos);
list.add(new ConnectionInformation(connectedInfo, newCon, currentTarget.getValue2().robot.getLinkedStation().side().getOpposite(), dir, (distance * 3) + 21));
} else {
if (CoordinateUtils.add(new DoubleCoordinates(pos), dir, 0.5).distanceTo(robotPos) > 0.05) {
// Not at station
continue;
}
for (Pair<DoubleCoordinates, ForgeDirection> canidatePos : ((LogisticsRoutingBoardRobot) robot.getBoard()).getConnectionDetails().localConnectedRobots) {
if (canidatePos.getValue1().equals(new DoubleCoordinates(startPipe))) {
continue;
}
double distance = CoordinateUtils.add(new DoubleCoordinates(canidatePos.getValue1()).center(), canidatePos.getValue2(), 0.5).distanceTo(robotPos);
TileEntity connectedPipeTile = canidatePos.getValue1().getTileEntity(pipe.getWorldObj());
if (!(connectedPipeTile instanceof LogisticsTileGenericPipe)) {
continue;
}
LogisticsTileGenericPipe connectedPipe = (LogisticsTileGenericPipe) connectedPipeTile;
if (!connectedPipe.isRoutingPipe()) {
continue;
}
IPipeInformationProvider connectedInfo = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(connectedPipe);
PipePluggable connectedPluggable = ((TileGenericPipe) connectedPipe.tilePart.getOriginal()).getPipePluggable(canidatePos.getValue2());
if (!(connectedPluggable instanceof RobotStationPluggable)) {
continue;
}
DockingStation connectedStation = ((RobotStationPluggable) connectedPluggable).getStation();
if (!connectedStation.isTaken()) {
continue;
}
EntityRobotBase connectedRobot = connectedStation.robotTaking();
if (connectedRobot == null) {
continue;
}
if (!(connectedRobot.getBoard() instanceof LogisticsRoutingBoardRobot)) {
continue;
}
if (connectedRobot.isDead) {
continue;
}
if (connectedRobot.getZoneToWork() != null && !connectedRobot.getZoneToWork().contains(robotPos.getXCoord(), robotPos.getYCoord(), robotPos.getZCoord())) {
continue;
}
if (!((LogisticsRoutingBoardRobot) connectedRobot.getBoard()).isAcceptsItems()) {
continue;
}
if (((LogisticsRoutingBoardRobot) connectedRobot.getBoard()).getCurrentTarget() != null && ((LogisticsRoutingBoardRobot) connectedRobot.getBoard()).getCurrentTarget().getValue2() != robot.getBoard()) {
continue;
}
DoubleCoordinates connectedRobotPos = new DoubleCoordinates(connectedRobot);
if (CoordinateUtils.add(new DoubleCoordinates(canidatePos.getValue1()).center(), canidatePos.getValue2(), 0.5).distanceTo(connectedRobotPos) > 0.05) {
// Not at station
continue;
}
EnumSet<PipeRoutingConnectionType> newCon = connection.clone();
newCon.removeAll(EnumSet.of(PipeRoutingConnectionType.canPowerFrom, PipeRoutingConnectionType.canPowerSubSystemFrom));
list.add(new ConnectionInformation(connectedInfo, newCon, canidatePos.getValue2().getOpposite(), dir, (distance * 3) + 21));
}
}
}
return list;
}
use of logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation in project LogisticsPipes by RS485.
the class TeleportPipes method getConnections.
@Override
public List<ConnectionInformation> getConnections(IPipeInformationProvider tile, EnumSet<PipeRoutingConnectionType> connection, ForgeDirection side) {
List<ConnectionInformation> list = new ArrayList<>();
if (tile.getTile() instanceof TileGenericPipe && ((TileGenericPipe) tile.getTile()).pipe != null) {
try {
LinkedList<? extends Pipe> pipes = getConnectedTeleportPipes(((TileGenericPipe) tile.getTile()).pipe);
list.addAll(pipes.stream().map(pipe -> new ConnectionInformation(SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(pipe.container), connection, side, ForgeDirection.UNKNOWN, 0)).collect(Collectors.toList()));
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
}
use of logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation in project LogisticsPipes by RS485.
the class PathFinder method getConnectedRoutingPipes.
private HashMap<CoreRoutedPipe, ExitRoute> getConnectedRoutingPipes(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connectionFlags, ForgeDirection side) {
HashMap<CoreRoutedPipe, ExitRoute> foundPipes = new HashMap<>();
boolean root = setVisited.size() == 0;
//Reset visited count at top level
if (setVisited.size() == 1) {
pipesVisited = 0;
}
//Break recursion if we have visited a set number of pipes, to prevent client hang if pipes are weirdly configured
if (++pipesVisited > maxVisited) {
return foundPipes;
}
//Break recursion after certain amount of nodes visited
if (setVisited.size() > maxLength) {
return foundPipes;
}
if (!startPipe.isRouterInitialized()) {
return foundPipes;
}
//Break recursion if we end up on a routing pipe, unless its the first one. Will break if matches the first call
if (startPipe.isRoutingPipe() && setVisited.size() != 0) {
CoreRoutedPipe rp = startPipe.getRoutingPipe();
if (rp.stillNeedReplace()) {
return foundPipes;
}
double size = 0;
for (Double dis : distances.values()) {
size += dis;
}
if (!rp.getUpgradeManager().hasPowerPassUpgrade()) {
connectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
foundPipes.put(rp, new ExitRoute(null, rp.getRouter(), ForgeDirection.UNKNOWN, side.getOpposite(), Math.max(1, size), connectionFlags, distances.size()));
return foundPipes;
}
//Visited is checked after, so we can reach the same target twice to allow to keep the shortest path
setVisited.add(new DoubleCoordinates(startPipe));
distances.put(new DoubleCoordinates(startPipe), startPipe.getDistance());
// first check specialPipeConnections (tesseracts, teleports, other connectors)
List<ConnectionInformation> pipez = SimpleServiceLocator.specialpipeconnection.getConnectedPipes(startPipe, connectionFlags, side);
for (ConnectionInformation specialConnection : pipez) {
if (setVisited.contains(new DoubleCoordinates(specialConnection.getConnectedPipe()))) {
//Don't go where we have been before
continue;
}
distances.put(new DoubleCoordinates(startPipe).center(), specialConnection.getDistance());
HashMap<CoreRoutedPipe, ExitRoute> result = getConnectedRoutingPipes(specialConnection.getConnectedPipe(), specialConnection.getConnectionFlags(), specialConnection.getInsertOrientation());
distances.remove(new DoubleCoordinates(startPipe).center());
for (Entry<CoreRoutedPipe, ExitRoute> pipe : result.entrySet()) {
pipe.getValue().exitOrientation = specialConnection.getExitOrientation();
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<>();
//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.getNextConnectedTile(direction);
if (tile == null) {
continue;
}
if (OrientationsUtil.isSide(direction)) {
if (root && tile instanceof ILogisticsPowerProvider) {
if (powerNodes == null) {
powerNodes = new ArrayList<>();
}
//If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe()) {
powerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));
} else {
powerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));
}
}
if (root && tile instanceof ISubSystemPowerProvider) {
if (subPowerProvider == null) {
subPowerProvider = new ArrayList<>();
}
//If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe()) {
subPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));
} else {
subPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));
}
}
}
connections.add(new Pair<>(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) {
Collection<TileEntity> list = SimpleServiceLocator.specialtileconnection.getConnectedPipes(tile);
if (!list.isEmpty()) {
connections.addAll(list.stream().map(pipe -> new Pair<>(pipe, direction)).collect(Collectors.toList()));
listTileEntity(tile);
continue;
}
if (!startPipe.getRoutingPipe().getUpgradeManager().hasPowerPassUpgrade()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
}
if (tile instanceof IInventory && startPipe.isRoutingPipe() && startPipe.getRoutingPipe() instanceof IDirectRoutingConnection && startPipe.canConnect(tile, direction, false)) {
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.pipeInformationManager.getInformationProviderFor(tile);
if (currentPipe != null && currentPipe.isRouterInitialized() && (isDirectConnection || SimpleServiceLocator.pipeInformationManager.canConnect(startPipe, currentPipe, direction, true))) {
listTileEntity(tile);
// DON'T USE THIS ANYMORE CAN CAUSE TROUBLE WITH MULTIBLOCKS
tile = null;
if (currentPipe.isMultiBlock()) {
currentPipe.getPartsOfPipe().forEach(this::listTileEntity);
}
if (setVisited.contains(new DoubleCoordinates(currentPipe))) {
//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 = null;
if (currentPipe instanceof IRouteProvider) {
List<RouteInfo> list = ((IRouteProvider) currentPipe).getConnectedPipes(direction.getOpposite());
if (list != null) {
result = new HashMap<>();
DoubleCoordinates pos = new DoubleCoordinates(currentPipe);
for (RouteInfo info : list) {
if (info.getPipe() == startPipe)
continue;
if (setVisited.contains(new DoubleCoordinates(info.getPipe()))) {
//Don't go where we have been before
continue;
}
distances.put(pos, currentPipe.getDistance() + info.getLength());
result.putAll(getConnectedRoutingPipes(info.getPipe(), nextConnectionFlags, direction));
distances.remove(pos);
}
}
}
if (result == null) {
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 DoubleCoordinates(startPipe));
distances.remove(new DoubleCoordinates(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();
}
}
//If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe() && root) {
for (ExitRoute e : foundPipes.values()) {
e.filters = new OneList<>(startPipe.getFirewallFilter());
}
}
return foundPipes;
}
use of logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation in project LogisticsPipes by RS485.
the class PathFinder method getConnectedRoutingPipes.
private HashMap<CoreRoutedPipe, ExitRoute> getConnectedRoutingPipes(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connectionFlags, EnumFacing side) {
HashMap<CoreRoutedPipe, ExitRoute> foundPipes = new HashMap<>();
final int setVisitedSize = setVisited.size();
boolean root = setVisitedSize == 0;
// Reset visited count at top level
if (setVisitedSize == 1) {
pipesVisited = 0;
}
// Break recursion if we have visited a set number of pipes, to prevent client hang if pipes are weirdly configured
pipesVisited += startPipe.getDistanceWeight() > 0 ? startPipe.getDistanceWeight() : 1;
if (pipesVisited > maxVisited) {
return foundPipes;
}
// Break recursion after certain amount of nodes visited
if (setVisitedSize > maxLength * 10) {
return foundPipes;
}
// Check size of setVisited first to speed up the process, so we don't sum the distances all the time
if (setVisitedSize > maxLength && distances.values().stream().mapToDouble(i -> Math.max(Math.min(i, 1), 0)).sum() > maxLength) {
return foundPipes;
}
if (!startPipe.isRouterInitialized()) {
return foundPipes;
}
// Break recursion if we end up on a routing pipe, unless its the first one. Will break if matches the first call
if (startPipe.isRoutingPipe() && setVisitedSize != 0) {
CoreRoutedPipe rp = startPipe.getRoutingPipe();
if (rp.stillNeedReplace()) {
return foundPipes;
}
double size = 0;
for (Double dis : distances.values()) {
size += dis;
}
if (!rp.getUpgradeManager().hasPowerPassUpgrade()) {
connectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
foundPipes.put(rp, new ExitRoute(null, rp.getRouter(), null, side.getOpposite(), Math.max(1, size), connectionFlags, distances.size()));
return foundPipes;
}
// Visited is checked after, so we can reach the same target twice to allow to keep the shortest path
setVisited.add(new DoubleCoordinates(startPipe));
distances.put(new DoubleCoordinates(startPipe), startPipe.getDistance() * startPipe.getDistanceWeight());
// first check specialPipeConnections (tesseracts, teleports, other connectors)
List<ConnectionInformation> pipez = SimpleServiceLocator.specialpipeconnection.getConnectedPipes(startPipe, connectionFlags, side);
for (ConnectionInformation specialConnection : pipez) {
if (setVisited.contains(new DoubleCoordinates(specialConnection.getConnectedPipe()))) {
// Don't go where we have been before
continue;
}
distances.put(new DoubleCoordinates(startPipe).center(), specialConnection.getDistance());
HashMap<CoreRoutedPipe, ExitRoute> result = getConnectedRoutingPipes(specialConnection.getConnectedPipe(), specialConnection.getConnectionFlags(), specialConnection.getInsertOrientation());
distances.remove(new DoubleCoordinates(startPipe).center());
for (Entry<CoreRoutedPipe, ExitRoute> pipe : result.entrySet()) {
pipe.getValue().exitOrientation = specialConnection.getExitOrientation();
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<Quartet<TileEntity, EnumFacing, Integer, Boolean>> connections = new ArrayDeque<>();
// Recurse in all directions
for (EnumFacing direction : EnumFacing.VALUES) {
if (root && side != null && !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.getNextConnectedTile(direction);
if (tile == null) {
continue;
}
if (root && (direction.getAxis() == EnumFacing.Axis.X || direction.getAxis() == EnumFacing.Axis.Z)) {
if (tile instanceof ILogisticsPowerProvider) {
if (powerNodes == null) {
powerNodes = new ArrayList<>();
}
// If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe()) {
powerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));
} else {
powerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));
}
} else if (tile instanceof ISubSystemPowerProvider) {
if (subPowerProvider == null) {
subPowerProvider = new ArrayList<>();
}
// If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe()) {
subPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));
} else {
subPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));
}
}
}
connections.add(new Quartet<>(tile, direction, 0, false));
}
while (!connections.isEmpty()) {
Quartet<TileEntity, EnumFacing, Integer, Boolean> quartet = connections.pollFirst();
TileEntity tile = quartet.getValue1();
EnumFacing direction = quartet.getValue2();
int resistance = quartet.getValue3();
boolean isDirectConnection = quartet.getValue4();
EnumSet<PipeRoutingConnectionType> nextConnectionFlags = EnumSet.copyOf(connectionFlags);
if (root) {
Collection<TileEntity> list = SimpleServiceLocator.specialtileconnection.getConnectedPipes(tile);
if (!list.isEmpty()) {
connections.addAll(list.stream().map(pipe -> new Quartet<>(pipe, direction, 0, false)).collect(Collectors.toList()));
listTileEntity(tile);
continue;
}
if (!startPipe.getRoutingPipe().getUpgradeManager().hasPowerPassUpgrade()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
}
}
if (!SimpleServiceLocator.pipeInformationManager.isPipe(tile) && tile.hasCapability(LogisticsPipes.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) && startPipe.isRoutingPipe() && startPipe.getRoutingPipe() instanceof IChannelRoutingConnection && startPipe.canConnect(tile, direction, false)) {
if (SimpleServiceLocator.connectionManager.hasChannelConnection(startPipe.getRoutingPipe().getRouter())) {
List<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(startPipe.getRoutingPipe().getRouter());
connections.addAll(connectedPipes.stream().map(pipe -> new Quartet<>((TileEntity) pipe.container, direction, ((IChannelRoutingConnection) startPipe.getRoutingPipe()).getConnectionResistance(), true)).collect(Collectors.toList()));
if (!connectedPipes.isEmpty()) {
continue;
}
}
}
if (tile == null) {
continue;
}
IPipeInformationProvider currentPipe = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile);
if (currentPipe != null && currentPipe.isRouterInitialized() && (isDirectConnection || SimpleServiceLocator.pipeInformationManager.canConnect(startPipe, currentPipe, direction, true))) {
listTileEntity(tile);
if (currentPipe.isMultiBlock()) {
currentPipe.getPartsOfPipe().forEach(this::listTileEntity);
}
if (setVisited.contains(new DoubleCoordinates(currentPipe))) {
// Don't go where we have been before
continue;
}
if (side != direction && !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.isOutputClosed(direction)) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canRouteTo);
}
}
if (currentPipe.isOnewayPipe()) {
nextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);
if (currentPipe.isOutputClosed(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 = null;
if (currentPipe instanceof IRouteProvider) {
List<RouteInfo> list = ((IRouteProvider) currentPipe).getConnectedPipes(direction.getOpposite());
if (list != null) {
result = new HashMap<>();
DoubleCoordinates pos = new DoubleCoordinates(currentPipe);
for (RouteInfo info : list) {
if (info.getPipe() == startPipe)
continue;
if (setVisited.contains(new DoubleCoordinates(info.getPipe()))) {
// Don't go where we have been before
continue;
}
distances.put(pos, (currentPipe.getDistance() * currentPipe.getDistanceWeight()) + info.getLength());
result.putAll(getConnectedRoutingPipes(info.getPipe(), nextConnectionFlags, direction));
distances.remove(pos);
}
}
}
if (result == null) {
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 DoubleCoordinates(startPipe));
distances.remove(new DoubleCoordinates(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();
}
}
// If we are a FireWall pipe add our filter to the pipes
if (startPipe.isFirewallPipe() && root) {
for (ExitRoute e : foundPipes.values()) {
e.filters = new OneList<>(startPipe.getFirewallFilter());
}
}
return foundPipes;
}
Aggregations