mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-11-22 11:53:29 +01:00
added proper priority handling
This commit is contained in:
parent
44a5d6b4ec
commit
4c764023f4
2 changed files with 67 additions and 14 deletions
|
@ -130,6 +130,11 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO module priority
|
||||||
|
public int getPriority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private IItemHandler getItemHandler(Direction dir) {
|
private IItemHandler getItemHandler(Direction dir) {
|
||||||
BlockState state = this.getBlockState();
|
BlockState state = this.getBlockState();
|
||||||
if (!state.get(PipeBlock.DIRECTIONS.get(dir)).isConnected())
|
if (!state.get(PipeBlock.DIRECTIONS.get(dir)).isConnected())
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.ellpeck.prettypipes.network;
|
package de.ellpeck.prettypipes.network;
|
||||||
|
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
import de.ellpeck.prettypipes.Registry;
|
import de.ellpeck.prettypipes.Registry;
|
||||||
import de.ellpeck.prettypipes.Utility;
|
import de.ellpeck.prettypipes.Utility;
|
||||||
import de.ellpeck.prettypipes.blocks.pipe.PipeBlock;
|
import de.ellpeck.prettypipes.blocks.pipe.PipeBlock;
|
||||||
|
@ -18,28 +19,40 @@ import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||||
import net.minecraftforge.common.util.Constants;
|
import net.minecraftforge.common.util.Constants;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import org.jgrapht.Graph;
|
||||||
import org.jgrapht.GraphPath;
|
import org.jgrapht.GraphPath;
|
||||||
|
import org.jgrapht.ListenableGraph;
|
||||||
|
import org.jgrapht.alg.connectivity.ConnectivityInspector;
|
||||||
|
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
|
||||||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||||
|
import org.jgrapht.event.GraphEdgeChangeEvent;
|
||||||
|
import org.jgrapht.event.GraphListener;
|
||||||
|
import org.jgrapht.event.GraphVertexChangeEvent;
|
||||||
|
import org.jgrapht.graph.DefaultListenableGraph;
|
||||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||||
|
import org.jgrapht.traverse.BreadthFirstIterator;
|
||||||
import org.jgrapht.traverse.ClosestFirstIterator;
|
import org.jgrapht.traverse.ClosestFirstIterator;
|
||||||
|
import org.jgrapht.traverse.DepthFirstIterator;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphListener<BlockPos, NetworkEdge> {
|
||||||
|
|
||||||
public final SimpleWeightedGraph<BlockPos, NetworkEdge> graph = new SimpleWeightedGraph<>(NetworkEdge.class);
|
public final ListenableGraph<BlockPos, NetworkEdge> graph;
|
||||||
private final DijkstraShortestPath<BlockPos, NetworkEdge> dijkstra = new DijkstraShortestPath<>(this.graph);
|
private final DijkstraShortestPath<BlockPos, NetworkEdge> dijkstra;
|
||||||
|
private final Map<BlockPos, List<BlockPos>> nodeToConnectedNodes = new HashMap<>();
|
||||||
private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>();
|
private final Map<BlockPos, PipeTileEntity> tileCache = new HashMap<>();
|
||||||
private final World world;
|
private final World world;
|
||||||
|
|
||||||
public PipeNetwork(World world) {
|
public PipeNetwork(World world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
|
this.graph = new DefaultListenableGraph<>(new SimpleWeightedGraph<>(NetworkEdge.class));
|
||||||
|
this.graph.addGraphListener(this);
|
||||||
|
this.dijkstra = new DijkstraShortestPath<>(this.graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -110,12 +123,8 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
||||||
PipeTileEntity startPipe = this.getPipe(startPipePos);
|
PipeTileEntity startPipe = this.getPipe(startPipePos);
|
||||||
if (startPipe == null)
|
if (startPipe == null)
|
||||||
return false;
|
return false;
|
||||||
ClosestFirstIterator<BlockPos, NetworkEdge> it = new ClosestFirstIterator<>(this.graph, startPipePos);
|
for (BlockPos pipePos : this.getOrderedDestinations(startPipePos)) {
|
||||||
while (it.hasNext()) {
|
PipeTileEntity pipe = this.getPipe(pipePos);
|
||||||
PipeTileEntity pipe = this.getPipe(it.next());
|
|
||||||
// don't try to insert into yourself, duh
|
|
||||||
if (pipe == startPipe)
|
|
||||||
continue;
|
|
||||||
BlockPos dest = pipe.getAvailableDestination(stack);
|
BlockPos dest = pipe.getAvailableDestination(stack);
|
||||||
if (dest != null)
|
if (dest != null)
|
||||||
return this.routeItemToLocation(startPipePos, pipe.getPos(), dest, itemSupplier);
|
return this.routeItemToLocation(startPipePos, pipe.getPos(), dest, itemSupplier);
|
||||||
|
@ -157,7 +166,8 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
||||||
|
|
||||||
private void addEdge(NetworkEdge edge) {
|
private void addEdge(NetworkEdge edge) {
|
||||||
this.graph.addEdge(edge.startPipe, edge.endPipe, edge);
|
this.graph.addEdge(edge.startPipe, edge.endPipe, edge);
|
||||||
this.graph.setEdgeWeight(edge, edge.pipes.size());
|
// only use size - 1 so that nodes aren't counted twice for multi-edge paths
|
||||||
|
this.graph.setEdgeWeight(edge, edge.pipes.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean allAround) {
|
private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean allAround) {
|
||||||
|
@ -215,4 +225,42 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
||||||
public static PipeNetwork get(World world) {
|
public static PipeNetwork get(World world) {
|
||||||
return world.getCapability(Registry.pipeNetworkCapability).orElse(null);
|
return world.getCapability(Registry.pipeNetworkCapability).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<BlockPos> getOrderedDestinations(BlockPos node) {
|
||||||
|
List<BlockPos> ret = this.nodeToConnectedNodes.get(node);
|
||||||
|
if (ret == null) {
|
||||||
|
ShortestPathAlgorithm.SingleSourcePaths<BlockPos, NetworkEdge> paths = this.dijkstra.getPaths(node);
|
||||||
|
// sort destinations first by their priority (eg trash pipes should be last)
|
||||||
|
// and then by their distance from the specified node
|
||||||
|
ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node))
|
||||||
|
.sorted(Comparator.<BlockPos>comparingInt(p -> this.getPipe(p).getPriority()).reversed().thenComparing(paths::getWeight))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
this.nodeToConnectedNodes.put(node, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edgeAdded(GraphEdgeChangeEvent<BlockPos, NetworkEdge> e) {
|
||||||
|
this.edgeModified(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void edgeRemoved(GraphEdgeChangeEvent<BlockPos, NetworkEdge> e) {
|
||||||
|
this.edgeModified(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void edgeModified(GraphEdgeChangeEvent<BlockPos, NetworkEdge> e) {
|
||||||
|
// uncache all connection infos that contain the removed edge's vertices
|
||||||
|
this.nodeToConnectedNodes.values().removeIf(
|
||||||
|
nodes -> nodes.stream().anyMatch(n -> n.equals(e.getEdgeSource()) || n.equals(e.getEdgeTarget())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void vertexAdded(GraphVertexChangeEvent<BlockPos> e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void vertexRemoved(GraphVertexChangeEvent<BlockPos> e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue