From 87de8e353d26995de2a93bb1350c962801e7cb1e Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Tue, 14 Apr 2020 14:10:58 +0200 Subject: [PATCH] got network connections fully working! --- .../prettypipes/blocks/pipe/PipeBlock.java | 6 ++ .../de/ellpeck/prettypipes/events/Events.java | 25 ----- .../prettypipes/network/NetworkEdge.java | 14 +++ .../prettypipes/network/PipeNetwork.java | 100 ++++++++++++------ 4 files changed, 89 insertions(+), 56 deletions(-) create mode 100644 src/main/java/de/ellpeck/prettypipes/network/NetworkEdge.java diff --git a/src/main/java/de/ellpeck/prettypipes/blocks/pipe/PipeBlock.java b/src/main/java/de/ellpeck/prettypipes/blocks/pipe/PipeBlock.java index 8d1e600..e00087a 100644 --- a/src/main/java/de/ellpeck/prettypipes/blocks/pipe/PipeBlock.java +++ b/src/main/java/de/ellpeck/prettypipes/blocks/pipe/PipeBlock.java @@ -5,6 +5,7 @@ import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.network.PipeNetwork; import net.minecraft.block.*; import net.minecraft.block.material.Material; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.InventoryHelper; @@ -95,6 +96,11 @@ public class PipeBlock extends ContainerBlock { return this.createState(context.getWorld(), context.getPos(), this.getDefaultState()); } + @Override + public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { + onStateChanged(worldIn, pos, state); + } + @Override public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) { return false; diff --git a/src/main/java/de/ellpeck/prettypipes/events/Events.java b/src/main/java/de/ellpeck/prettypipes/events/Events.java index eced7c6..9cda371 100644 --- a/src/main/java/de/ellpeck/prettypipes/events/Events.java +++ b/src/main/java/de/ellpeck/prettypipes/events/Events.java @@ -2,18 +2,11 @@ package de.ellpeck.prettypipes.events; import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.network.PipeNetwork; -import net.minecraft.particles.ParticleType; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.particles.RedstoneParticleData; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import org.jgrapht.graph.DefaultWeightedEdge; @Mod.EventBusSubscriber public final class Events { @@ -22,22 +15,4 @@ public final class Events { public static void onWorldCaps(AttachCapabilitiesEvent event) { event.addCapability(new ResourceLocation(PrettyPipes.ID, "network"), new PipeNetwork(event.getObject())); } - - @SubscribeEvent - public static void onWorldTick(TickEvent.WorldTickEvent event) { - if (event.phase != TickEvent.Phase.END) - return; - if (event.world.getGameTime() % 5 != 0) - return; - - PipeNetwork network = PipeNetwork.get(event.world); - for (DefaultWeightedEdge edge : network.graph.edgeSet()) { - BlockPos start = network.graph.getEdgeSource(edge); - BlockPos end = network.graph.getEdgeTarget(edge); - - RedstoneParticleData data = new RedstoneParticleData(((start.getX() * 181923 + end.getX()) % 255) / 255F, ((start.getY() * 128391 + end.getY()) % 255) / 255F, ((start.getZ() * 123891 + end.getZ()) % 255) / 255F, 1); - ((ServerWorld) event.world).spawnParticle(data, start.getX() + 0.5F, start.getY() + 0.5F, start.getZ() + 0.5F, 1, 0, 0, 0, 0); - ((ServerWorld) event.world).spawnParticle(data, end.getX() + 0.5F, end.getY() + 0.5F, end.getZ() + 0.5F, 1, 0, 0, 0, 0); - } - } } diff --git a/src/main/java/de/ellpeck/prettypipes/network/NetworkEdge.java b/src/main/java/de/ellpeck/prettypipes/network/NetworkEdge.java new file mode 100644 index 0000000..a301c60 --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/network/NetworkEdge.java @@ -0,0 +1,14 @@ +package de.ellpeck.prettypipes.network; + +import net.minecraft.tileentity.TileEntity; +import org.jgrapht.graph.DefaultWeightedEdge; + +import java.util.ArrayList; +import java.util.List; + +public class NetworkEdge extends DefaultWeightedEdge { + + public TileEntity startPipe; + public List pipes = new ArrayList<>(); + public TileEntity endPipe; +} diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index f28c7fb..2d19816 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -2,7 +2,9 @@ package de.ellpeck.prettypipes.network; import com.google.common.collect.Sets; import de.ellpeck.prettypipes.Registry; +import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.blocks.pipe.PipeBlock; +import de.ellpeck.prettypipes.blocks.pipe.PipeTileEntity; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; @@ -31,8 +33,8 @@ import java.util.Set; public class PipeNetwork implements ICapabilitySerializable { - public final SimpleWeightedGraph graph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); - private final DijkstraShortestPath dijkstra = new DijkstraShortestPath<>(this.graph); + public final SimpleWeightedGraph graph = new SimpleWeightedGraph<>(NetworkEdge.class); + private final DijkstraShortestPath dijkstra = new DijkstraShortestPath<>(this.graph); private final World world; public PipeNetwork(World world) { @@ -68,48 +70,84 @@ public class PipeNetwork implements ICapabilitySerializable { } public void onPipeChanged(BlockPos pos, BlockState state) { - Set> neighbors = this.findConnectedNodesInPipe(pos, state); + List neighbors = this.createAllEdges(pos, state, true); // if we only have one neighbor, then there can't be any new connections if (neighbors.size() <= 1 && !this.graph.containsVertex(pos)) return; - for (Pair node : neighbors) - this.refreshNode(node.getLeft(), this.world.getBlockState(node.getLeft())); - System.out.println(this.graph); + for (NetworkEdge edge : neighbors) { + BlockPos end = edge.endPipe.getPos(); + this.refreshNode(end, this.world.getBlockState(end)); + } + System.out.println(this.graph.toString()); } private void refreshNode(BlockPos pos, BlockState state) { - Set edges = this.graph.edgesOf(pos); + Set edges = this.graph.edgesOf(pos); this.graph.removeAllEdges(new ArrayList<>(edges)); - for (Pair node : this.findConnectedNodesInPipe(pos, state)) { - DefaultWeightedEdge edge = this.graph.addEdge(pos, node.getLeft()); - this.graph.setEdgeWeight(edge, node.getRight()); + for (NetworkEdge edge : this.createAllEdges(pos, state, false)) { + this.graph.addEdge(edge.startPipe.getPos(), edge.endPipe.getPos(), edge); + this.graph.setEdgeWeight(edge, edge.pipes.size()); } } - private Set> findConnectedNodesInPipe(BlockPos pos, BlockState state) { - Set> set = new HashSet<>(); - this.findConnectedNodesInPipe(pos, state, set, Sets.newHashSet(pos), 0); - return set; - } - - private void findConnectedNodesInPipe(BlockPos pos, BlockState state, Set> nodes, Set seen, int iterations) { - if (!(state.getBlock() instanceof PipeBlock)) - return; + private List createAllEdges(BlockPos pos, BlockState state, boolean allAround) { + List edges = new ArrayList<>(); for (Direction dir : Direction.values()) { - if (!state.get(PipeBlock.DIRECTIONS.get(dir)).isConnected()) - continue; - BlockPos offset = pos.offset(dir); - if (seen.contains(offset)) - continue; - seen.add(offset); - if (this.graph.containsVertex(offset)) { - nodes.add(Pair.of(offset, iterations)); - break; - } else { - this.findConnectedNodesInPipe(offset, this.world.getBlockState(offset), nodes, seen, iterations + 1); - } + NetworkEdge edge = this.createEdge(pos, state, dir, allAround); + if (edge != null) + edges.add(edge); } + return edges; + } + + private NetworkEdge createEdge(BlockPos pos, BlockState state, Direction dir, boolean allAround) { + if (!allAround && !state.get(PipeBlock.DIRECTIONS.get(dir)).isConnected()) + return null; + BlockPos currPos = pos.offset(dir); + BlockState currState = this.world.getBlockState(currPos); + if (!(currState.getBlock() instanceof PipeBlock)) + return null; + NetworkEdge edge = new NetworkEdge(); + PipeTileEntity startPipe = Utility.getTileEntity(PipeTileEntity.class, this.world, pos); + if (startPipe != null) { + edge.startPipe = startPipe; + edge.pipes.add(startPipe); + } + edge.pipes.add(Utility.getTileEntity(PipeTileEntity.class, this.world, currPos)); + + Set seen = new HashSet<>(); + seen.add(pos); + seen.add(currPos); + while (true) { + // if we found a vertex, we can stop since that's the next node + // we do this here since the first offset pipe also needs to check this + if (this.graph.containsVertex(currPos)) { + edge.endPipe = edge.pipes.get(edge.pipes.size() - 1); + return edge; + } + + boolean found = false; + for (Direction nextDir : Direction.values()) { + if (!currState.get(PipeBlock.DIRECTIONS.get(nextDir)).isConnected()) + continue; + BlockPos offset = currPos.offset(nextDir); + if (seen.contains(offset)) + continue; + seen.add(offset); + BlockState offState = this.world.getBlockState(offset); + if (!(offState.getBlock() instanceof PipeBlock)) + continue; + edge.pipes.add(Utility.getTileEntity(PipeTileEntity.class, this.world, offset)); + currPos = offset; + currState = offState; + found = true; + break; + } + if (!found) + break; + } + return null; } public static PipeNetwork get(World world) {