mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-11-25 21:18:34 +01:00
pipe networks, part 1
This commit is contained in:
parent
ad92be8d7b
commit
bf60a40457
5 changed files with 215 additions and 1 deletions
|
@ -83,13 +83,20 @@ sourceSets.main.resources {
|
|||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = "https://dvs1.progwml6.com/files/maven"
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
embed
|
||||
compile.extendsFrom(embed)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft 'net.minecraftforge:forge:1.15.2-31.1.19'
|
||||
embed "org.jgrapht:jgrapht-core:1.4.0"
|
||||
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2:api")
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.2")
|
||||
|
@ -108,6 +115,7 @@ jar {
|
|||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
])
|
||||
}
|
||||
from configurations.embed.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import de.ellpeck.prettypipes.blocks.pipe.PipeGui;
|
|||
import de.ellpeck.prettypipes.blocks.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.items.ExtractionUpgradeItem;
|
||||
import de.ellpeck.prettypipes.items.WrenchItem;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -15,8 +16,13 @@ import net.minecraft.item.BlockItem;
|
|||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.extensions.IForgeContainerType;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
@ -26,6 +32,8 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
|||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Mod.EventBusSubscriber(bus = Bus.MOD)
|
||||
public final class Registry {
|
||||
|
||||
|
@ -36,6 +44,9 @@ public final class Registry {
|
|||
}
|
||||
};
|
||||
|
||||
@CapabilityInject(PipeNetwork.class)
|
||||
public static Capability<PipeNetwork> pipeNetworkCapability;
|
||||
|
||||
public static Item wrenchItem;
|
||||
public static Item extractionUpgradeItem;
|
||||
|
||||
|
@ -80,7 +91,18 @@ public final class Registry {
|
|||
}
|
||||
|
||||
public static void setup(FMLCommonSetupEvent event) {
|
||||
CapabilityManager.INSTANCE.register(PipeNetwork.class, new Capability.IStorage<PipeNetwork>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public INBT writeNBT(Capability<PipeNetwork> capability, PipeNetwork instance, Direction side) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(Capability<PipeNetwork> capability, PipeNetwork instance, Direction side, INBT nbt) {
|
||||
|
||||
}
|
||||
}, () -> null);
|
||||
}
|
||||
|
||||
public static void setupClient(FMLClientSetupEvent event) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.ellpeck.prettypipes.blocks.pipe;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
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.player.PlayerEntity;
|
||||
|
@ -149,6 +150,26 @@ public class PipeBlock extends ContainerBlock {
|
|||
if (tile != null)
|
||||
Utility.dropInventory(tile, tile.upgrades);
|
||||
}
|
||||
|
||||
PipeNetwork network = PipeNetwork.get(world);
|
||||
int connections = 0;
|
||||
boolean inventory = false;
|
||||
for (EnumProperty<ConnectionType> prop : DIRECTIONS.values()) {
|
||||
ConnectionType value = newState.get(prop);
|
||||
if (!value.isConnected())
|
||||
continue;
|
||||
connections++;
|
||||
if (value == ConnectionType.CONNECTED_INVENTORY) {
|
||||
inventory = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inventory || connections > 2) {
|
||||
network.addNode(pos, newState);
|
||||
} else {
|
||||
network.removeNode(pos);
|
||||
}
|
||||
network.onPipeChanged(pos, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -157,7 +178,9 @@ public class PipeBlock extends ContainerBlock {
|
|||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
|
||||
if (tile != null)
|
||||
Utility.dropInventory(tile, tile.upgrades);
|
||||
|
||||
PipeNetwork network = PipeNetwork.get(worldIn);
|
||||
network.removeNode(pos);
|
||||
network.onPipeChanged(pos, state);
|
||||
super.onReplaced(state, worldIn, pos, newState, isMoving);
|
||||
}
|
||||
}
|
||||
|
|
43
src/main/java/de/ellpeck/prettypipes/events/Events.java
Normal file
43
src/main/java/de/ellpeck/prettypipes/events/Events.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
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 {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onWorldCaps(AttachCapabilitiesEvent<World> 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);
|
||||
}
|
||||
}
|
||||
}
|
118
src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java
Normal file
118
src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
package de.ellpeck.prettypipes.network;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.blocks.pipe.PipeBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.jgrapht.Graphs;
|
||||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||
import org.jgrapht.graph.DefaultEdge;
|
||||
import org.jgrapht.graph.DefaultWeightedEdge;
|
||||
import org.jgrapht.graph.SimpleGraph;
|
||||
import org.jgrapht.graph.SimpleWeightedGraph;
|
||||
import org.jheaps.tree.FibonacciHeap;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
||||
|
||||
public final SimpleWeightedGraph<BlockPos, DefaultWeightedEdge> graph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class);
|
||||
private final DijkstraShortestPath<BlockPos, DefaultWeightedEdge> dijkstra = new DijkstraShortestPath<>(this.graph);
|
||||
private final World world;
|
||||
|
||||
public PipeNetwork(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
return cap == Registry.pipeNetworkCapability ? LazyOptional.of(() -> (T) this) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
return new CompoundNBT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundNBT nbt) {
|
||||
|
||||
}
|
||||
|
||||
public void addNode(BlockPos pos, BlockState state) {
|
||||
if (!this.graph.containsVertex(pos)) {
|
||||
this.graph.addVertex(pos);
|
||||
this.refreshNode(pos, state);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNode(BlockPos pos) {
|
||||
if (this.graph.containsVertex(pos))
|
||||
this.graph.removeVertex(pos);
|
||||
}
|
||||
|
||||
public void onPipeChanged(BlockPos pos, BlockState state) {
|
||||
Set<Pair<BlockPos, Integer>> neighbors = this.findConnectedNodesInPipe(pos, state);
|
||||
// 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<BlockPos, Integer> node : neighbors)
|
||||
this.refreshNode(node.getLeft(), this.world.getBlockState(node.getLeft()));
|
||||
System.out.println(this.graph);
|
||||
}
|
||||
|
||||
private void refreshNode(BlockPos pos, BlockState state) {
|
||||
Set<DefaultWeightedEdge> edges = this.graph.edgesOf(pos);
|
||||
this.graph.removeAllEdges(new ArrayList<>(edges));
|
||||
|
||||
for (Pair<BlockPos, Integer> node : this.findConnectedNodesInPipe(pos, state)) {
|
||||
DefaultWeightedEdge edge = this.graph.addEdge(pos, node.getLeft());
|
||||
this.graph.setEdgeWeight(edge, node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Pair<BlockPos, Integer>> findConnectedNodesInPipe(BlockPos pos, BlockState state) {
|
||||
Set<Pair<BlockPos, Integer>> set = new HashSet<>();
|
||||
this.findConnectedNodesInPipe(pos, state, set, Sets.newHashSet(pos), 0);
|
||||
return set;
|
||||
}
|
||||
|
||||
private void findConnectedNodesInPipe(BlockPos pos, BlockState state, Set<Pair<BlockPos, Integer>> nodes, Set<BlockPos> seen, int iterations) {
|
||||
if (!(state.getBlock() instanceof PipeBlock))
|
||||
return;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static PipeNetwork get(World world) {
|
||||
return world.getCapability(Registry.pipeNetworkCapability).orElse(null);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue