package polly.rx.core.orion.pathplanning; import java.util.Collection; import java.util.HashSet; import java.util.Set; import polly.rx.core.orion.Orion; import polly.rx.core.orion.QuadrantProvider; import polly.rx.core.orion.WormholeProvider; import polly.rx.core.orion.model.Quadrant; import polly.rx.core.orion.model.Sector; import polly.rx.core.orion.model.SectorType; import polly.rx.core.orion.model.Wormhole; import polly.rx.core.orion.pathplanning.Graph.LazyBuilder; class UniverseBuilder implements LazyBuilder<Sector, EdgeData> { private final Set<Sector> done; private final Collection<Wormhole> block; private final Collection<Sector> entryPortalBlock; private final RouteOptions options; private final QuadrantProvider quadProvider; private final WormholeProvider holeProvider; public UniverseBuilder(RouteOptions options) { this.quadProvider = Orion.INSTANCE.getQuadrantProvider(); this.holeProvider = Orion.INSTANCE.getWormholeProvider(); this.options = options; this.done = new HashSet<>(); this.block = new HashSet<>(); this.entryPortalBlock = new HashSet<>(); } public void startOverAndBlock(Wormhole hole) { this.done.clear(); if (hole instanceof EntryPortalWormhole) { this.entryPortalBlock.add(hole.getTarget()); } else { this.block.add(hole); } } @Override public void collectIncident(Graph<Sector, EdgeData> graph, Sector source) { if (this.done.add(source)) { // add wormhole edges final Collection<Wormhole> holes = holeProvider.getWormholes( source, quadProvider); for (final Wormhole hole : holes) { if (this.block.contains(hole)) { continue; } final Quadrant targetQuad = quadProvider.getQuadrant( hole.getTarget()); final EdgeData d = EdgeData.wormhole(hole); this.addNeighbour(targetQuad, hole.getTarget().getX(), hole.getTarget().getY(), graph, source, d); } // add entry portals for (final Sector portal : quadProvider.getEntryPortals()) { if (this.options.doBlockEntryPortal()) { if (this.entryPortalBlock.contains(portal)) { continue; } } final EdgeData d = EdgeData.entryPortal(source, portal); final Quadrant targetQuad = quadProvider.getQuadrant(portal); this.addNeighbour(targetQuad, portal.getX(), portal.getY(), graph, source, d); } // add personal portals for (final Sector personal : this.options.personalPortals) { if (this.options.doBlockEntryPortal()) { if (this.entryPortalBlock.contains(personal)) { continue; } } final EdgeData d = EdgeData.entryPortal(source, personal); final Quadrant targetQuad = quadProvider.getQuadrant(personal); this.addNeighbour(targetQuad, personal.getX(), personal.getY(), graph, source, d); } // add direct neighbours final int x = source.getX(); final int y = source.getY(); final Quadrant quad = quadProvider.getQuadrant(source); for (int i = -1; i < 2; ++i) { for (int j = -1; j < 2; ++j) { final boolean diagonal = Math.abs(i) == 1 && Math.abs(j) == 1; final EdgeData d = EdgeData.sector(diagonal); this.addNeighbour(quad, x + i, y + j, graph, source, d); } } } } private void addNeighbour(Quadrant quad, int x, int y, Graph<Sector, EdgeData> graph, Sector source, EdgeData edgeData) { if (x < 0 || x > quad.getMaxX() || y < 0 || y > quad.getMaxY() || (x == source.getX() && y == source.getY())) { return; } final Sector neighbour = quad.getSector(x, y); if (neighbour.getType() != SectorType.NONE) { final Graph<Sector, EdgeData>.Node vSource = graph.getNode(source); final Graph<Sector, EdgeData>.Node vTarget = graph.getNode(neighbour, neighbour); vSource.edgeTo(vTarget, edgeData); } } }